在查看Java线程池实现的源码时,对于线程池内部worker生命周期有一个不解的地方:当worker所持有的task,或者线程队列中的task都被执行完以后,为什么worker要被移除线程池的worker集合。
追踪源码的过程大致是:
查看execute(Runnable command)方法,发现了addWorker(command, true)的调用
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);
进入addWorker(Runnable firstTask, boolean core),发现了worker线程的启动
if (workerAdded) {
t.start();
workerStarted = true;
}
Worker类的run方法即调用ThreadPoolExecutor中的runWorker方法。
在runWorker方法的最后调用了processWorkerExit方法。
} finally {
processWorkerExit(w, completedAbruptly);
}
在processWorkerExit中发现:
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
completedTaskCount += w.completedTasks;
workers.remove(w);
} finally {
mainLock.unlock();
}
worker被从线程集合workers移除了。
所以疑惑或者问题是:
线程持中其实是不保有一定数量可用线程,如果当task队列里面没有要处理的任务,原先创造的worker工作线程都会逐步被移除,直到下次再有新的task到来,才又会创建新的worker工作线程??
题主可以点进去getTask方法里面看下,runWorker的while循环提交里面
1.timedOut[1040], 首次获取任务是否可以超时, 默认false
2.[1043-1050], 检查线程池状态, 如果处于关闭状态则返回null。根据代码,会关闭所有线程
3.timed ,允许超时?[1055], 是否允许核心线程超时 || 当前活动线程是否大于核心线程
4.[1057-1062]。 分成两段,同时为真才会执行[1059]-[1061]
5.[1065-1070]根据timed参数, 是有永久阻塞获取任务
图片的源代码是jdk1.8, 我说的可能比较粗糙。题主可以去看下这篇文章