背景
Java 中的 ThreadPoolExecutor 是 JUC 包中十分重要的成员,主要提供了一个线程池管理的工作。关于它的用法,很多博客都有提及,包括 corePoolSize, 阻塞队列 blockQueue, 最大池大小 maxPoolSize, 拒绝策略 RejectedExecutionHandler ,和存活时间 keepAliveTime, 都已经有很多文章。我们都知道 keepAliveTime 指的是当当前线程池中线程大于 corePoolSize 的时候,如果超过 keepAliveTime 还没有新的任务,则释放大于 corePoolSize 部分的线程。但是它是怎么实现的,本文我就来给大家剖析一下。
头脑风暴
在开始看源码之前,我们先思考一下,如果要做到超时释放,应该怎么做。一种简单的方式就是启动一个线程,这个线程不断的轮询线程池当前线程的状态,发现有空闲的线程则调用中断方法尝试中断线程。
从提交开始看起
execute 方法
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 方法很好理解,就是判断当前线程池中活跃线程是否小于 corePoolSize, 如果超过,则进入阻塞队列,还不行就创建新 worker,如果创建失败了,那么就进入拒绝策略。我们可以看到关键的执行方法是 addWorker 方法,然后我们看看 addWorker 做了什么
addWorker 方法
addWorker 分为两个部分,我们先来看第一个部分
addWorker 第一部分
retry:
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
// Check if queue empty only if necessary.
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))