Executors使用静态工厂方法创建的线程池,对外返回ExecutorService实例,而实际创建的对象使用的是ThreadPoolExecutor类的实例。
以newFixedThreadPool(int nThreads)为例分析源码:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue());
}
方法中只是调用了ThreadPoolExecutor的一个构造方法:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
ThreadPoolExecutor中一共有四个构造方法,其中三个都是调用this(....)构造创建实例,也就是下面的构造:
//this(....)调用的是下面的构造方法
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue 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.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
构造函数中参数解析:
创建好线程池之后,下面要用线程池执行任务。调用线程池执行任务的方法有两类:execute 和 submit 。execute方法在线程池的超类Executor中定义,在ThreadPoolExecutor中实现;submit方法是在ExecutorService中定义,在AbstractExecutorService中实现。
/**
* 在将来某个时候执行给定的任务。
* 如果无法提交任务供执行,要么是因为此执行器已关闭,要么是因为其容量已达到,
* 则由当前{@code RejectedExecutionHandler}处理该任务。
*/
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
//如果运行线程数小于核心线程数,创建新的线程执行任务
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
//线程池处于运行状态并且加入队列成功
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
//线程池不处于运行状态且加入队列失败,则创建线程(创建的是非核心线程)
else if (!addWorker(command, false))
//创建线程失败,则采取阻塞处理的方式
reject(command);
}
execute执行线程任务,主要三个步骤:
AbstractExecutorService抽象类中有三个submit重载方法:
public Future> submit(Runnable task) {
if (task == null) throw new NullPointerException();
RunnableFuture ftask = newTaskFor(task, null);
execute(ftask);
return ftask;
}
public Future submit(Runnable task, T result) {
if (task == null) throw new NullPointerException();
RunnableFuture ftask = newTaskFor(task, result);
execute(ftask);
return ftask;
}
public Future submit(Callable task) {
if (task == null) throw new NullPointerException();
RunnableFuture ftask = newTaskFor(task);
execute(ftask);
return ftask;
}
submit方法,将线程执行记过存放到Future中。
方法中涉及到Future接口、RunnableFuture接口和newTaskFor()方法:
protected RunnableFuture newTaskFor(Runnable runnable, T value) {
return new FutureTask(runnable, value);
}
这里又出现了一个类FutureTask,FutureTask是RunnableFuture的实现类,而RunnableFuture接口又是Future和Runnable的子类。
FutureTask是一个包装类,API中对FutureTask的描述:“一个可取消的异步计算。提供了启动和取消计算、查询计算是否完成以及检索计算结果的方法。只有在计算完成后才可检索结果;如果计算尚未完成,{@code get}方法将阻塞。一旦计算完成,就不能重新启动或取消计算”
关闭线程池有两个方法:shutdown()和shutdownNow()
/**
* 将正在执行的任务完成,但是不会接受新的任务。任务执行完毕后关闭线程池
*
*/
public void shutdown() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
advanceRunState(SHUTDOWN);
interruptIdleWorkers();
onShutdown(); // hook for ScheduledThreadPoolExecutor
} finally {
mainLock.unlock();
}
tryTerminate();
}
/**
* 尝试停止所有正在积极执行的任务,停止处理等待的任务,并返回等待执行的任务列表。
* 从该方法返回时,将从任务队列中删除这些任务。
*/
public List shutdownNow() {
List tasks;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
advanceRunState(STOP);
interruptWorkers();
tasks = drainQueue();
} finally {
mainLock.unlock();
}
tryTerminate();
return tasks;
}
public boolean isShutdown() {
return ! isRunning(ctl.get());
}