1

刚翻了一下源码ThreadPoolExecutor发现一旦时间达到keepAliveTime的设定值并且allowCoreThreadTimeOut为true就会中断所有空闲的worker。

对我来说有点奇怪,它只能在 runState >= SHUTDOWN 时调用中断方法:

下面的代码来自getTask().ThreadPoolExecutor

Runnable getTask() {
...
if (workerCanExit()) {
    if (runState >= SHUTDOWN) // Wake up others
        interruptIdleWorkers();
    return null;
   }
}

这是否意味着所有空闲线程只能在 runState >= SHUTDOWN(SHUTDOWN、STOP 或 TERMINATED)时被中断?也就是说当状态为RUNNING时它们不会被中断。

4

3 回答 3

2

你说的对。调用此getTask() 方法ThreadPoolExecutor以获取工作线程运行的下一个任务。此代码块仅在方法调用未标识任何 Runnable 任务以执行时才执行。因此,如果没有发现要执行的内容,它必须检查关闭状态。

来自java文档workerCanExit()

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

于 2012-04-30T14:20:18.237 回答
1

例如,将 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正在处理task-0;task-1 留在工作队列中;workerThread-1 正在处理任务 2;workerThread-2 正在处理任务 3;workerThread-3 正在处理 task-4,workerThreadCount==4。

  1. workerThread-3 完成了task-4,此时[workerThreadCount==4] > [corePoolSize==1],它将通过workQueue.poll(keepAliveTime) 从workQueue 中获取下一个task(task-1)。然后,继续处理task-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. 然后workerThread-0完成task-0,因为[workerThreadCount==4] > [corePoolSize==1],它仍然通过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完成task-1,它会以与workerThread-1相同的方式返回。这次workerThreadCount==1。
  5. 然后workerThread-2完成了task-3,但是这次[workerThreadCount==1]不超过[corePoolSize==1],所以当workQueue.take()从workQueue获取下一个任务时会阻塞,直到有一个workQueue 中的可用任务。它的状态是WAITING

注意:源代码来自JDK8。

于 2018-07-10T06:20:26.973 回答
0

确切地。正确的任务(如果允许中断)必须检查自身是否有中断标志并终止(即从 run() 返回)。

于 2012-04-30T14:14:10.367 回答