Executors是jdk中的一个工具包,提供了几种线程池的构建;分析一下各个线程池的实现与使用场景避免用错。

汇总

newFixedThreadPool

1
2
3
4
5
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}

关注这几个线程池的入参:

  1. 核心线程数与最大线程数相等;
  2. 线程超时时间为0;
  3. 任务队列是LinkedBlockingQueue;

根据参数就可以判断这个线程池的特性:

线程池中的线程最大可以达到nThreads,由于线程没有超时时间所以线程达到nThreads后这些线程会一直缓存着不会结束。任务队列是LinkedBlockingQueue,可以理解为任务加入没有上限(实际是最大整数)。注意LinkedBlockingQueue达到上限只是等待,而不是添加失败。

使用场景

newFixedThreadPool是比较通用的线程池,不过线程没有超时时间,所以要判断好线程数避免过多的线程空闲无用。

newCachedThreadPool

1
2
3
4
5
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}

关注这几个线程池的入参:

  1. 核心线程数为0,最大线程数为最大整型;
  2. 线程超时时间为60秒;
  3. 任务队列是SynchronousQueue;

SynchronousQueue是堵塞队列得一种,其特性是put操作和take操作必须是互相唤醒的,比如:put操作,必须take操作唤醒,take操作必须put操作唤醒,没有take操作,多个put操作都堵塞,等待一个一个take操作来一个一个唤醒,同理,take操作也一样,跟他的名字一样,同步队列,就好像,你是救我的药,我也是救你的药
如果没有take在等待,直接执行offer会立即返回false,而线程池中使用的就是offer方法。

特性

可缓存的线程池,调用execute()方法将重用之前构造的线程(如果线程可用)。如果每有线程可用,则创建一个新线程并加入池中。终止并从缓存中移除那些超过60秒未使用的线程。由于SynchronousQueue的特性(offer方法),使得没有空闲线程时就会添加新线程。

场景

适合用于任务执行时间较短的情况。

newScheduledThreadPool

1
2
3
4
5
6
7
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}

一个普通的延时/定时任务线程池。

newWorkStealingPool

1
2
3
4
5
6
public static ExecutorService newWorkStealingPool() {
return new ForkJoinPool
(Runtime.getRuntime().availableProcessors(),
ForkJoinPool.defaultForkJoinWorkerThreadFactory,
null, true);
}

newWorkStealingPool适合使用在很耗时的操作,但是newWorkStealingPool不是ThreadPoolExecutor的扩展,它是新的线程池类ForkJoinPool的扩展,但是都是在统一的一个Executors类中实现,由于能够合理的使用CPU进行对任务操作(并行操作),所以适合使用在很耗时的任务中。

newSingleThreadExecutor

1
2
3
4
5
6
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}

一个只有一个线程的线程池。

FinalizableDelegatedExecutorService实现了finalize()方法,在finalize方法中执行shutdown()。

参考

SynchronousQueue源码分析