线程池四种创建线程方式 和 java并发

四种线程池的创建都是重写了ThreadPoolExecutor()方法:缓存,定长,定时,单例

阿里java代码规范不允许使用Executors创建线程池,原因

1)FixedThreadPool 和 SingleThreadPool: 允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。

2)CachedThreadPool 和 ScheduledThreadPool: 允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。

没有拒绝任务的处理方式

使用ThreadPoolExecutor创建线程池

构造方法如下:

线程池四种创建线程方式 和 java并发_第1张图片

其中ThreadFactory(创建线程的工厂)用不到,系统使用默认方式创建线程,RejectedExecutionHandler(拒绝策略)抛异常用的,一般也用不上。

corePoolSize     核心线程数(实际运行的线程数)

maximumPoolSize    最大线程数

keepAliveTime          闲置的线程最大存活时间(非核心)

keepAliveTime 当线程池中线程数量大于corePoolSize时,闲置线程最长可以存活的时间

TimeUnit时间单位

 

线程池四种创建线程方式 和 java并发_第2张图片

使用线程池批量提交任务:

package com.jixu.Chaoshen;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;

/**
 * Created by xc on 2019/1/7.
 * 线程池批量提交任务
 */
public class TaskDemo implements Callable {
    private int num;
    public TaskDemo() {
    }
    public TaskDemo(int num) {
        this.num = num;
    }
    
    static ExecutorService mExecutor = new ThreadPoolExecutor(2,15,
            10,TimeUnit.MILLISECONDS,new LinkedBlockingQueue(13));
    
    @Override
    public Integer call() throws Exception {
        Random r = new Random();
        long time = (r.nextInt(10) + 1) * 1000;
//        Thread.sleep(time);
        System.out.println("耗时:" + time / 1000);
        return  num++;
    }
    public void add()throws Exception{
        List list=new ArrayList<>();
        for(int i=0;i<12;i++){
           list.add(new TaskDemo(i));//每一个数都加一
        }
        List> futures = mExecutor.invokeAll(list,5000, TimeUnit.MILLISECONDS);//任务的返回
        Iterator> iterator = futures.iterator();
        while(iterator.hasNext()){
            Future next = iterator.next();
            System.out.println(next.get());
        }
    mExecutor.shutdown();
    }
    public static void main(String[] args) {
        try {
            new TaskDemo().add();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
}
线程池里面创建了2个核心线程,最大线程数为15,队列为阻塞队列,设置可存储任务大小为15。任务12,

synchronized(同步锁)

线程池四种创建线程方式 和 java并发_第3张图片

public class Testsyncronized {
    public static void main(String[] args) {
//开了两个线程去执行taskM任务,谁获得cup的调度谁去执行
        TaskM taskM = new TaskM();
        Thread thread1 = new Thread(taskM, "SyncThread1");
        Thread thread2 = new Thread(taskM, "SyncThread2");//代码是错的
        thread1.start();
        thread2.start();

    }
}
class TaskM implements Runnable{
//    Object object=new Object();
    int i=10;
    @Override
    public void run() {
       while(true){
           synchronized (TaskM.class){
               if(i>=0){
                   try {
                       Thread.sleep(200);
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
                   System.out.println("当前线程"+Thread.currentThread().getName()+",,"+i--);
            
                       }
               }
               
           }
           
       }
    }

 

Volatile关键字

轻量级的锁:用来确保将变量的更新操作通知到其他线程。(直接操作内存中的数据)

可以保证数据可见。

java提供了volatile来保证可见性。

当一个变量被volatile修饰后,表示着线程本地内存无效,当一个线程修改共享变量后他会立即被更新到主内存中,当其他线程读取共享变量时,它会直接从主内存中读取。当然,synchronize和锁都可以保证可见性。

java 并发编程的原子性:提供了互斥访问,同一时刻只能有一个线程对类或者方法进行操作.

线程池四种创建线程方式 和 java并发_第4张图片

深入理解java虚拟机:

所以对于对于多线程中需要及时刷新到内存的变量可以用voliate去修饰

public class TestDemo{
  
    public static void main(String[] args) {//
        ThreadDemo threadDemo = new ThreadDemo();
        new Thread(threadDemo).start();
//        try {
//            Thread.sleep(2000);
//        } catch (InterruptedException e) {//zje
//            e.printStackTrace();
//        }
        
        while(true) {
//            synchronized (threadDemo) {
                if (threadDemo.isFlage()) {//
                    System.out.println("22222222");
                    break;
//                }
            }
        }    }
  
}

class ThreadDemo implements Runnable{
    private volatile   boolean flage=false;
    public boolean isFlage() {
        return flage;
    }
    
    public void setFlage(boolean flage) {
        this.flage = flage;
    }
    
    
    @Override
    public void run() {
        flage=true;
//        try {
//            Thread.sleep(2000);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//
        System.out.println("111111111");
    }
}

至于原子性则需要通过锁或者Synchronized来解决了。

 

你可能感兴趣的:(线程池四种创建线程方式 和 java并发)