目录
相关接口和实现类
由一个顶级接口 Executor ,两个核心子接口 ExecutorService、ScheduledExecutorService和一组实现类组成。
顶级接口Executor的作用是用来定义线程池中提交并执行线程任务的核心方法:execute( )方法。未来所有要提交的线程任务都由这个方法执行 。
ExecutorService接口作为子接口,在原有的基础上扩展了awaitTermination()、submit()、shutdown()等专门用于管理线程任务的方法。
AbstractExecutorService为ExecutorService的抽象实现类,为它的子类提供了submit()、invokeAll()等部分方法的公共实现。但是由于在不同线程池中的核心方法exuecte()执行策略不同,所以在AbstractExecutorService并未提供该方法的具体实现。常见子类有ThreadPoolExecutor和ForkJoinPool,实现了不同的线程池。
ThreadPoolExecutor线程池通过Worker工作线程、BlockingQueue阻塞工作队列以及RejectedExecutionHandler拒绝策略实现了一个标准的线程池;
ForkJoinPool是一个基于分治思想的线程池实现类,通过分叉(fork)、合并(join)的方式,将一个大任务拆分成多个小任务,并且为每个工作线程提供一个工作队列,减少竞争,实现并行的线程任务执行方式,所以ForkJoinPool适合计算密集型场景,是ThreadPoolExecutor的一种补充。
ScheduledThreadPoolExecutor类是ThreadPoolExecutor类的子类,它是按照时间周期执行线程任务的线程池实现类,通常用于作业调度相关的业务场景。它使用DelayedWorkQueue延时工作队列,这是一个按照任务执行时间进行排序的优先级工作队列,所以这也是ScheduledThreadPoolExecutor能按照时间周期来执行线程任务的主要原因。
工作线程Worker类
线程池中每一个Worker对象,都代表其中的一个工作线程。
当线程池通过调用execute( )方法执行1个线程任务时,会调用addWorker( )方法创建一个Worker工作线程对象。并且会把创建好的Worker工作线程添加到HashSet<Worker> workers中,统一由线程池进行管理。(当前工作线程数小于核心线程数时)
通过源码我们看到,Worker类是 ThreadPoolExecutor类中的私有内部类,保存了每个Worker要执行的Runnable线程任务和Thread线程对象。
当创建一个Worker时,会以构造方法的形式保存Runnable线程任务,同时通过 ThreadFactory线程工厂,为该Worker分配一个Thread。这样每个Worker都将通过这种形式绑定一个真正的Thread。
另外,当Thread被JVM调度执行时,线程会自动执行Worker的run( )方法,run( )方法内部通过调用runWorker( )方法,最终实现Worker保存的线程任务的执行。
值得重视的是:当Worker第一次执行完成线程任务后,这个Worker的工作线程并不会销毁,而是会以循环的方式,通过线程池的getTask( )方法获取阻塞工作队列中新的线程任务,并通过当前所绑定的Thread线程完成线程任务的执行,从而实现了线程池中线程的重用。
核心方法:execute( )
ThreadPoolExecutor线程池中,会通过execute(Runnable task)方法执行Runnable类型的线程任务。
ThreadPoolExecutor完整实现了Executor接口定义execute()方法,这个方法作用是执行一个Runnable类型的线程任务。整体的执行流程是:
- 首先通过AtomicInteger类型的ctl对象,获取线程池的工作状态和工作线程数;
- 然后判断当前的工作线程数;
- 如果当前的工作线程数小于核心线程数,则通过addWorker( )方法创建新的Worker工作线程,并将其添加至workers工作线程集合;
- 如果当前工作线程数大于等于核心线程数,并且线程池处于Running状态,那么会将线程任务缓存至workQueue阻塞工作队列,等待某个空闲工作线程获取并执行该任务;
- 如果工作队列也缓存任务失败,意味着工作队列已满。那么线程池则会重新通过addWorker( )方法尝试创建新的Worker;
- 这次的创建会判断当前工作线程数是否超出最大线程数。如果没有超出则创建;如果已经超出,则返回false,创建失败,下一个提交的线程任务如果想要执行,线程池会直接执行拒绝策略;
下面是部分源代码
public class ThreadPoolExecutor
{
// 线程池执行Runnable线程任务
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
// 获取线程池的状态和工作线程数
int c = ctl.get();
// 工作线程的数量小于核心线程数
if (workerCountOf(c) < corePoolSize) {
// 创建新的Worker工作线程
if (addWorker(command, true))
return;
// 创建失败,重新获取线程池的状态和工作线程数
c = ctl.get();
}
// 如果线程池处于RUNNING状态,缓存线程任务至工作队列
if (isRunning(c) && workQueue.offer(command)) {
// 任务缓存成功
// 重新获取线程池的状态和工作线程数
int recheck = ctl.get();
// 如果线程池不是处于RUNNING状态,则删除任务
if (! isRunning(recheck) && remove(command))
// 执行拒绝策略
reject(command);
// 如果工作线程数等于零
// 通过addWorker()方法检查线程池状态和工作队列
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
// 如果缓存线程任务至工作队列
// 尝试创建新的工作线程
// 创建时,判断工作线程数是否超出最大线程数
// 如果没有超出,创建成功
// 如果已经超出,创建失败
else if (!addWorker(command, false))
// 执行拒绝策略
reject(command);
}
}
核心方法:addWorker( )方法
在execute( )方法执行的过程中,会通过addWorker( )方法创建工作线程,用于执行当前线程任务。
通过源码我们发现,这个方法的整个执行过程可分为两个部分:检查线程池的状态和当前工作线程数,用于创建并执行工作线程。
1. 检查线程池当前运行状态和工作线程数量
private boolean addWorker(Runnable firstTask, boolean core) {
// 第1部分:检查线程池的状态和工作线程数量
// 循环检查线程池的状态,直到符合创建工作线程的条件,通过retry标签break退出
retry:
for (;;) {
// 通过ctl对象,获取当前线程池的运行状态
int c = ctl.get();
int rs = runStateOf(c);
// 如果线程池处于开始关闭的状态(获取线程任务为空,同时工作队列不等于空)
// 则工作线程创建失败
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;
// 检查工作线程数量
for (;;) {
// 通过ctl对象,获取当前线程池中工作线程数量
int wc = workerCountOf(c);
// 工作线程数量如果超出最大容量或者核心线程数(最大线程数)
// 则工作线程创建失败
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize))
return false;
// 通过ctl对象,将当前工作线程数量+1,并通过retry标签break退出外层循环
if (compareAndIncrementWorkerCount(c))
break retry;
// 再次获取线程池状态,检查是否发生变化
c = ctl.get(); // Re-read ctl
if (runStateOf(c) != rs)
continue retry;
// else CAS failed due to workerCount change; retry inner loop
}
}
// 第2部分:创建并执行工作线程....
}
2. 创建并执行工作线程
private boolean addWorker(Runnable firstTask, boolean core) {
// 第1部分:检查线程池的状态和工作线程数量....
// 第2部分:创建并执行工作线程....
boolean workerStarted = false; // 工作线程是否已经启动
boolean workerAdded = false; // 工作线程是否已经保存
Worker w = null;
try {
// 创建新工作线程,并通过线程工厂创建Thread线程
w = new Worker(firstTask);
// 获取新工作线程的Thread线程对象,用于启动真正的线程
final Thread t = w.thread;
if (t != null) {
// 获取线程池的ReentrantLock主锁对象
// 确保在添加和启动线程时的同步与安全
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// 检查线程池状态
int rs = runStateOf(ctl.get());
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
// 检查Thread线程对象的状态是否已经处于启动状态
if (t.isAlive())
throw new IllegalThreadStateException();
// 保存工作线程
workers.add(w);
// 记录线程池曾经达到过的最大工作线程数量
int s = workers.size();
if (s > largestPoolSize)
largestPoolSize = s;
workerAdded = true;
}
} finally {
mainLock.unlock();
}
// 添加工作线程后,正式启动线程
if (workerAdded) {
t.start();
workerStarted = true;
}
}
} finally {
if (! workerStarted)
addWorkerFailed(w);
}
// 返回线程启动状态
return workerStarted;
}