getTask()方法
/*
* 依赖当前的配置阻塞或等待指定时间获取一个任务,如果在发生以下情况那么
* 当前的worker必须退出,则返回null
* 1. 当前线程数超过了最大线程数(可能由于动态修改了最大线程数)
* 2. 线程池状态未STOP
* 3. 线程池状态为SHUTDOWN 并且任务队列未空
* 4. 当前线程等待获取任务超时,并且要释放(比如设置了核心线程数可以超时或者线程数>核心线程数)
*
* @return 返回下一个任务,如果当前worker必须退出,返回null,并对线程数-1
*/
private Runnable getTask() {
boolean timedOut = false; // 上一次poll方法是否超时了
retry:
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
decrementWorkerCount();
return null;
}
boolean timed; // 标示当前线程超时是否退出
for (;;) {
int wc = workerCountOf(c);
//如果设置了核心线程可以超时或者线程数>核心线程数,那么当前线程如果回去任务超时了,则退出
timed = allowCoreThreadTimeOut || wc > corePoolSize;
//如果工作线程数小于最大线程数并且当前线程超时不是超时退出或上一次没有超时,跳出循环,继续后面获取任务
if (wc <= maximumPoolSize && ! (timedOut && timed))
break;
//如果工作线程数>最大线程数,或者当前线程超时要退出,并且上一次已经超时了,
//CAS 工作线程数-1,workerCount-1成功返回空,否则重试
if (compareAndDecrementWorkerCount(c))
return null;
//如果运行状态变化了,从外层循环重新校验线程池状态
//否则直接执行内层循环
c = ctl.get(); // Re-read ctl
if (runStateOf(c) != rs)
continue retry;
}
try {
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
if (r != null)
return r;
timedOut = true;//取任务超时
} catch (InterruptedException retry) {
timedOut = false;
}
}
}