/**
* Performs blocking or timed wait for a task, depending on
* current configuration settings, or returns null if this worker
* must exit because of any of:
* 1. There are more than maximumPoolSize workers (due to
* a call to setMaximumPoolSize).
* 2. The pool is stopped.
* 3. The pool is shutdown and the queue is empty.
* 4. This worker timed out waiting for a task, and timed-out
* workers are subject to termination (that is,
* {@code allowCoreThreadTimeOut || workerCount > corePoolSize})
* both before and after the timed wait, and if the queue is
* non-empty, this worker is not the last thread in the pool.
*
* @return task, or null if the worker must exit, in which case
* workerCount is decremented
*/
// 什么情况下会返回null?
// 1.rs >= STOP
// 2.SHUTDOWN && workQueue.isEmpty()
// 3.线程池中的线程数超过最大限制时,会有一部分线程返回null
// wc > maximumPoolSize && (wc > 1 || workQueue.isEmpty())
// 4.线程池中的线程数超过corePoolSize时,会有一部分线程返回null
// (timed && timedOut) && (wc > 1 || workQueue.isEmpty())
private Runnable getTask() {
// 当前线程获取任务是否超时
boolean timedOut = false; // Did the last poll() time out?
// 自旋
for (;;) {
// 获取最新ctl的值
int c = ctl.get();
// 获取线程池当前运行状态
int rs = runStateOf(c);
// Check if queue empty only if necessary.
// 条件1.rs >= SHUTDOWN
// true --> 当前线程池状态不为running
// 条件2.(rs >= STOP || workQueue.isEmpty())
// 条件2.1 rs >= STOP
// true --> 当前线程池的状态最低也是stop了,则getTask会失败
// 条件2.2 workQueue.isEmpty()
// 前置条件:线程池的状态是SHUTDOWN
// true --> queue为空,则getTask会失败
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
// 返回null,runWorker就会将返回值为null的线程执行退出线程池的逻辑
// worker count减一(CAS+自旋)
decrementWorkerCount();
return null;
}
// 执行到这里,有两种情况:
// 1. 线程池状态是RUNNING
// 2. 线程池状态是SHUTDOWN,且queue不为空
// 只有这两种情况可以创建线程
// 获取到worker的数量
int wc = workerCountOf(c);
// Are workers subject to culling?
// 条件:allowCoreThreadTimeOut || wc > corePoolSize
// true --> 当前线程池获取线程支持超时机制,queue.poll(xxx,xxx);在获取task超时的情况下,下一次自旋可能就返回null了
// false -> 当前线程池获取线程不支持超时机制的。当前线程会使用queue.take()
// allowCoreThreadTimeOut 是否允许核心线程超时
// - 若为true,则说明不论那种线程,获取task的时候都要加入超时机制
// - 若为false,则获取核心线程的任务不允许超时,但是获取非核心线程的任务加入超时机制
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
// 条件1.(wc > maximumPoolSize || (timed && timedOut))
// 条件1.1 wc > maximumPoolSize 可能会成立的原因:
// 外部线程调用了setMaximumPoolSize方法,将线程池最大线程数设置为比初始化的时候要小
// 条件1.2 timed && timedOut
// 有超时机制,且上一次循环时,使用poll方式获取任务时,超时了
// 条件1代表,线程达到了回收的标准,可以被回收。等确实需要回首时再回收
// 条件2.(wc > 1 || workQueue.isEmpty())
// 条件2.1 wc > 1
// true --> 说明线程池中还有其它线程,当前线程可以直接回收 --> 返回null
// 条件2.2 workQueue.isEmpty()
// 前置条件:wc == 1
// true --> 说明当前任务队列已经空了,最后一个线程也可以放心退出
//
if ((wc > maximumPoolSize || (timed && timedOut))
&& (wc > 1 || workQueue.isEmpty())) {
// 使用CAS的方式让workerCount减一
// CAS成功的线程返回null
// CAS失败的线程continue自旋
// CAS失败的原因:1.其它线程先减了数量;2.线程池的状态发生了变化
if (compareAndDecrementWorkerCount(c))
return null;
// 再次自旋时,timed可能为false
// 因为当前线程CAS失败,可能是因为其它线程成功退出导致的
// 再次自旋时,wc <= corePoolSize --> 即属于不需要回收的范围内了
continue;
}
// 以下为获取任务的逻辑
try {
// 获取任务
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
// 任务不为null,返回任务
if (r != null)
return r;
// 执行到这里,获取任务超时了(如果不为null,则已经返回了;为null,则说明获取task超时)
// 下一次自旋的时候,可能就会返回null了
timedOut = true;
} catch (InterruptedException retry) {
timedOut = false;
}
}
}