阿里巴巴推荐创建线程池方式

322 阅读3分钟

概念

使用ThreadPoolExecutor创建

JDK1.8中构造方法如下:

 public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              RejectedExecutionHandler handler) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), handler);
    }
变量意义
corePoolSize核心线程池大小
maximumPoolSize最大线程池大小
keepAliveTime空闲线程的存活时间
unit空闲线程保持存活的时间的单位。
workQueue阻塞任务队列,当要执行的任务超出corePoolSize ,那么此时将把任务放入队列中。
handler提交任务超出maxmumPoolSize+workQueue时的拒绝策略

存活时间

keepAliveTime即空闲线程(大于corePoolSize 小于maximumPoolSize 的线程)保持存活的时间,超出这个时间,线程将被销毁。

存活时间单位

TimeUnit.NANOSECONDS		//		千分之一微秒(纳秒)
TimeUnit.MICROSECONDS		//		千分之一毫秒(微妙)
TimeUnit.MILLISECONDS		//		千分之一秒(毫秒)
TimeUnit.SECONDS			//		秒		
TimeUnit.MINUTES			//		分
TimeUnit.HOURS				//		小时
TimeUnit.DAYS				//		天

任务队列

  • ArrayBlockingQueue:是一个基于数组结构的有界阻塞队列,此队列按 FIFO(先进先出)原则对元素进行排序。
  • LinkedBlockingQueue:一个基于链表结构的阻塞队列,此队列按 FIFO (先进先出) 排序元素,吞吐量通常要高于 ArrayBlockingQueue。静态工厂方法Executors.newFixedThreadPool() 使用了这个队列。
  • SynchronousQueue:一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlockingQueue,静态工厂方法Executors.newCachedThreadPool 使用了这个队列。
  • PriorityBlockingQueue:一个具有优先级的无限阻塞队列。

拒绝策略

  • AbortPolicy 中止策略 :默认的饱和策略,该策略将抛出为检查的RejectedExecutionException.调用者可以捕获这个异常,然后根据需求编写自己的代码。
  • DiscardPolicy 抛弃策略: 当新提交的任务无法保存到队列中等待执行时,抛弃策略会悄悄抛弃该任务
  • DiscardOldestPolicy 抛弃最旧的策略: 抛弃下一个将被执行的任务,然后添加新提交的任务
  • CallerRunsPolicy 调用者运行策略: 该策略实现了一种调用机制,该策略既不抛弃任务,也不抛出异常,而是将某些任务回退到调用者,从而降低新任务的流量。它不会在线程池的某个线程中执行新提交的任务,而是在一个调用了execute的线程中执行该任务(一般该调用者是main线程)

小demo

public class ThreadPoolDemo implements Callable<String> {
    /**
     * 核心线程池大小
     */
    public static final int CORE_POOL_SIZE = 5;
    /**
     * 最大线程池大小
     */
    public static final int MAX_POOL_SIZE = 10;
    /**
     * 阻塞任务队列大小
     */
    public static final int QUEUE_CAPACITY = 100;
    /**
     * 空闲线程存活时间
     */
    public static final Long KEEP_ALIVE_TIME = 1L;

    @Override
    public String call() throws Exception {
        return Thread.currentThread().getName();
    }

    public static void main(String[] args) {
        //通过ThreadPoolExecutor构造函数自定义参数创建
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                CORE_POOL_SIZE,
                MAX_POOL_SIZE,
                KEEP_ALIVE_TIME,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(QUEUE_CAPACITY),
                new ThreadPoolExecutor.CallerRunsPolicy());

        List<Future<String>> futureList = new ArrayList<>();
        Callable<String> callable = new ThreadPoolDemo();
        for (int i = 0; i < 10; i++) {
            //提交任务到线程池
            Future<String> future = executor.submit(callable);
            //将返回值 future 添加到 list,我们可以通过 future 获得 执行 Callable 得到的返回值
            futureList.add(future);
        }
        //获取返回结果
        for (Future<String> fut : futureList) {
            try {
                System.out.println(new Date() + "::" + fut.get());
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        }
        //关闭线程池
        executor.shutdown();
    }
}