canExit =
runState >= STOP
|| workQueue.isEmpty()
|| (allowCoreThreadTimeOut && poolSize > Math.max(1, corePoolSize)); 上述代码反映,在三种情况下允许当前Worker终止。
我的疑问在第三种情况【 (allowCoreThreadTimeOut && poolSize > Math.max(1, corePoolSize));】
如果allowCoreThreadTimeOut 为false,但是当前线程数poolSize大于核心线程池大小corePoolSize,那么当前工作线程作为workerCanExit()调用之前没有从队列中成功获取到任务的闲置线程,为什么不能终止?
总感觉应改为【poolSize > Math.max(1, corePoolSize))|| allowCoreThreadTimeOut】想了好久,想不明白。
runState >= STOP
|| workQueue.isEmpty()
|| (allowCoreThreadTimeOut && poolSize > Math.max(1, corePoolSize)); 上述代码反映,在三种情况下允许当前Worker终止。
我的疑问在第三种情况【 (allowCoreThreadTimeOut && poolSize > Math.max(1, corePoolSize));】
如果allowCoreThreadTimeOut 为false,但是当前线程数poolSize大于核心线程池大小corePoolSize,那么当前工作线程作为workerCanExit()调用之前没有从队列中成功获取到任务的闲置线程,为什么不能终止?
总感觉应改为【poolSize > Math.max(1, corePoolSize))|| allowCoreThreadTimeOut】想了好久,想不明白。
我的意思是当allowCoreThreadTimeOut 为false时也存在需要中断当前Worker的情况,
而源代码体现的意思是如果allowCoreThreadTimeOut 为false,就一定不可中断当前Worker。
麻烦再看看,谢谢,想不通。
Runnable getTask() {
for (;;) { // 无限循环!
try {
int state = runState;
// 1、STOP|TERMINATED态,不处理queue中的任务
if (state > SHUTDOWN) {
return null;
} Runnable r;
// 2、SHUTDOWN态,线程池不会再接收新任务,也就是说不会有新任务添加到队列中,所以选不阻塞的poll()!
if (state == SHUTDOWN) {
r = workQueue.poll();
}
// 3、RUNNING态
// 3.1、如果 (poolSize > corePoolSize) || 允许核心线程超时;
// XXX 当前工作线程可能不能马上获取到任务,需要用带超时的poll方法实现keepAliveTime的超时终止机制
else if (poolSize > corePoolSize || allowCoreThreadTimeOut) {
r = workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS);
}
// 3.2、否则 (poolSize <= corePoolSize) && 不允许核心线程超时;
// 这种情况当前工作线程就是核心线程,且不允许被终止,所以调用阻塞的take方法!
else {
r = workQueue.take();
}
if (r != null){
return r;
}
// 如果代码走的是2或3.1这两个poll相关的执行路径中的一个,且没有获取到任务,则再检测一下是否可以终止当前工作线程。
if (workerCanExit()) {
// 如果经判断可以终止当前Worker,那么在终止当前Worker前,若线程池状态为已关闭,则可中断其它所有闲置的Worker。
if (runState >= SHUTDOWN) {
interruptIdleWorkers();
}
// 通过返回null终止当前Worker
return null;
}
// 如果经判断不能终止当前Worker,则继续下次循环再次尝试获取任务!
} catch (InterruptedException ie) {
// On interruption, re-check runState
}
}
}
/**
* 出现下面三种情况即可终止:
* 1、如果pool的状态为 STOP|TERMINATED
* 2、队列为空
* 3、允许回收核心线程 并且 当前线程数大于核心线程池大小
*/
private boolean workerCanExit() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
boolean canExit;
try {
canExit = runState >= STOP || workQueue.isEmpty()
|| (allowCoreThreadTimeOut && poolSize > Math.max(1, corePoolSize)); // XXX ???
} finally {
mainLock.unlock();
}
return canExit;
}