我刚刚浏览了ThreadPoolExecutor
的源代码,发现一旦时间达到keepAliveTime的设定值并且allowCoreThreadTimeOut为真,它将中断所有空闲工作。
对我来说有点奇怪,它只能在runState> = SHUTDOWN时调用中断方法:
以下代码来自getTask()
的方法ThreadPoolExecutor
。
Runnable getTask() {
...
if (workerCanExit()) {
if (runState >= SHUTDOWN) // Wake up others
interruptIdleWorkers();
return null;
}
}
这是否意味着只有当runState> = SHUTDOWN(SHUTDOWN,STOP或TERMINATED)时才能中断所有空闲线程?也就是说,当状态正在运行时,它们不会被打断。
答案 0 :(得分:2)
你是对的。调用getTask()
中的ThreadPoolExecutor
方法来获取工作线程运行的下一个任务。仅当方法调用未标识任何可执行的Runnable任务时,才会执行此代码块。因此,如果没有找到任何执行,它必须检查关闭状态。
来自workerCanExit()
检查无法获取任务的工作线程是否可以退出。如果池正在停止,或者队列为空,或者至少有一个线程可以处理可能非空队列,我们允许工作线程死亡,即使允许核心超时也是如此。
答案 1 :(得分:0)
完全。正确的任务(如果允许中断)必须检查自身是否有中断标志并终止(即从run()返回)。
答案 2 :(得分:0)
例如,将ThreadPoolExecutor配置为:corePoolSize = 1,maxPoolSize = 5,workQueueSize = 1,keepAliveTime = 60s,allowCoreThreadTimeOut = false。
同时提供5个任务(每个任务都很耗时)时,这5个任务之一将进入workQueue,其他4个任务将几乎同时由新创建的4个工作线程立即处理。
这时,辅助线程的总和为4(workerThreadCount = 4)。一旦一个线程完成其任务,它将通过调用阻塞方法workQueue.take()或workQueue.poll(keepAliveTime)在workQueue上等待。至于哪种阻塞方法将由workerThreadCount决定。
例如(假设),在某个时间点,workerThread-0正在处理任务-0;任务1停留在workQueue中; workerThread-1正在处理任务2; workerThread-2正在处理任务3; workerThread-3正在处理任务4,而workerThreadCount == 4。
workerThread-3完成任务4,这次[workerThreadCount == 4]> [corePoolSize == 1],它将通过workQueue.poll(keepAliveTime)从workQueue中获取下一个任务(task-1)。 。然后,继续处理任务1,这次是workerThreadCount == 4。 ThreadPoolExecutor.java的代码段如下:
while (task != null || (task = getTask()) != null) {
task.run();
}
private Runnable getTask() {
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
Runnable r = timed ? workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : workQueue.take();
}
注意:源代码来自JDK8。