ThreadPoolExecutor如何中断空闲线程?

时间:2012-04-30 13:53:56

标签: java java.util.concurrent

我刚刚浏览了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)时才能中断所有空闲线程?也就是说,当状态正在运行时,它们不会被打断。

3 个答案:

答案 0 :(得分:2)

你是对的。调用getTask()中的ThreadPoolExecutor方法来获取工作线程运行的下一个任务。仅当方法调用未标识任何可执行的Runnable任务时,才会执行此代码块。因此,如果没有找到任何执行,它必须检查关闭状态。

来自workerCanExit()

的java doc
  

检查无法获取任务的工作线程是否可以退出。如果池正在停止,或者队列为空,或者至少有一个线程可以处理可能非空队列,我们​​允许工作线程死亡,即使允许核心超时也是如此。

答案 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。

  1. 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(); }

  2. 然后,由于[workerThreadCount == 4]> [corePoolSize == 1],workerThread-0完成了任务0,它仍然通过workQueue.poll(keepAliveTime)从workQueue中获取下一个任务。但是,这次workQueue为空,因此将在其上阻塞workerThread-0,并且workerThread-0的状态为 TIMED_WAITING 。一旦keepAliveTime经过,workQueue.poll(keepAliveTime)将返回null,接下来,workerThread-0将从Runnable.run()返回,并变为 TERMINATED 。这次是workerThreadCount == 3。
  3. 然后workerThread-1完成task-2,它将以与workerThread-0相同的方式返回。这次workerThreadCount == 2。
  4. 然后workerThread-3完成任务1,它将以与workerThread-1相同的方式返回。这次workerThreadCount == 1。
  5. 然后workerThread-2完成任务3,但是这次[workerThreadCount == 1]不超过[corePoolSize == 1],因此当通过workQueue.take()从workQueue中获取下一个任务时,它将被阻止,直到workQueue中有一个可用任务。其状态为正在等待

注意:源代码来自JDK8。