Executors就是Executor多了一个s,但是它跟Executor没有依赖关系。它其实是一个工厂或者说是一个工具类,能够生产ExecutorService、ScheduleExecutorService、Callable、ThreadFactory实例。本篇文章暂时就讲解生产线程池的方法。
一、单线程线程池
从以下代码知道,单线程的线程池核心线程数和最大线程数都是1,所以不管什么情况它都是单线程运行的。另外,阻塞队列用了LInkedBlockingQueue,保存的等待任务为MAX_VALUE个。
public static ExecutorService newSingleThreadExecutor() {
// 实例化一个内部类,其实也是一个ExecutorService
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
// 这个内部类就是重写了finalize()方法,让GC回收之前调用shutdow()方法
static class FinalizableDelegatedExecutorService
extends DelegatedExecutorService {
FinalizableDelegatedExecutorService(ExecutorService executor) {
super(executor);
}
protected void finalize() {
super.shutdown();
}
}
// 下面两个方法是ThreadPoolExecutor的构造器方法
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
二、缓存线程池
缓存线程池核心线程数为0,使用SynchronousQueue作为阻塞队列。SynchronousQueue队列的offer()方法是这样的,当调用offer的时候正好有空闲线程的时候返回true,否则返回false。也就是说当没有空闲线程的时候,线程池会创建一个线程去执行任务,最大线程数是Integer.MAX_VALUE。另外当空闲线程大于60秒还没有任务执行的时候会退出。
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
三、固定线程池
固定线程池的核心线程数和最大线程数都是入参大小,所以它最多也就创建指定大小的线程。另外,阻塞队列用了LInkedBlockingQueue,保存的等待任务为MAX_VALUE个。
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
四、总结
Executors暂且讲解这么多,常用的场景也就是这三个方法了,留着其他方法后面补充吧。