在没有额外设置参数的默认情况下,线程池的核心线程是不会被回收的,即使它们处于空闲状态。但是ThreadPoolExecutor 还是提供了一个参数来控制这个行为,通过allowCoreThreadTimeOut(true)设置后,核心线程在空闲超过`keepAliveTime时就会被回收。
在java.util.concurrent.java.util.concurrent可以找到
/**
* If false (default), core threads stay alive even when idle.
* If true, core threads use keepAliveTime to time out waiting
* for work.
*/
// 翻译:如果为 false(默认值),即使在空闲状态下核心线程也保持存活。如果为 true,
// 核心线程使用 keepAliveTime 来超时等待工作。
private volatile boolean allowCoreThreadTimeOut;
/**
* Main worker run loop. Repeatedly gets tasks from queue and
* executes them, while coping with a number of issues:
*
* 1. We may start out with an initial task, in which case we
* don't need to get the first one. Otherwise, as long as pool is
* running, we get tasks from getTask. If it returns null then the
* worker exits due to changed pool state or configuration
* parameters. Other exits result from exception throws in
* external code, in which case completedAbruptly holds, which
* usually leads processWorkerExit to replace this thread.
*
* 2. Before running any task, the lock is acquired to prevent
* other pool interrupts while the task is executing, and then we
* ensure that unless pool is stopping, this thread does not have
* its interrupt set.
*
* 3. Each task run is preceded by a call to beforeExecute, which
* might throw an exception, in which case we cause thread to die
* (breaking loop with completedAbruptly true) without processing
* the task.
*
* 4. Assuming beforeExecute completes normally, we run the task,
* gathering any of its thrown exceptions to send to afterExecute.
* We separately handle RuntimeException, Error (both of which the
* specs guarantee that we trap) and arbitrary Throwables.
* Because we cannot rethrow Throwables within Runnable.run, we
* wrap them within Errors on the way out (to the thread's
* UncaughtExceptionHandler). Any thrown exception also
* conservatively causes thread to die.
*
* 5. After task.run completes, we call afterExecute, which may
* also throw an exception, which will also cause thread to
* die. According to JLS Sec 14.20, this exception is the one that
* will be in effect even if task.run throws.
*
* The net effect of the exception mechanics is that afterExecute
* and the thread's UncaughtExceptionHandler have as accurate
* information as we can provide about any problems encountered by
* user code.
*
* @param w the worker
*/
/**
主要的工作线程运行循环。反复从队列中获取任务并执行它们,同时处理一些问题:
我们可能以一个初始任务开始,在这种情况下我们不需要获取第一个任务。否则,只要线程池在运行,我们就从 getTask 方法获取任务。如果它返回 null,那么由于线程池状态或配置参数的改变,工作线程退出。其他退出情况是由于外部代码抛出异常,在这种情况下 completedAbruptly 被设置为 true,这通常会导致 processWorkerExit 方法替换这个线程。
在运行任何任务之前,获取锁以防止在任务执行期间其他对线程池的中断,然后我们确保除非线程池正在停止,否则这个线程的中断标志不会被设置。
每个任务运行之前会调用 beforeExecute 方法,这个方法可能会抛出异常,在这种情况下我们使线程死亡(以 completedAbruptly 为 true 打破循环)而不处理任务。
假设 beforeExecute 正常完成,我们运行任务,收集任务抛出的任何异常以发送给 afterExecute。我们分别处理 RuntimeException、Error(规范保证我们捕获这两种异常)和任意的 Throwables。因为我们不能在 Runnable.run 中重新抛出 Throwables,所以我们在抛出时将它们包装在 Errors 中(传递给线程的 UncaughtExceptionHandler)。任何抛出的异常也会保守地导致线程死亡。
在 task.run 完成后,我们调用 afterExecute,它也可能抛出异常,这也会导致线程死亡。根据 JLS 第 14.20 节,这个异常将是有效的,即使 task.run 抛出了异常。
异常处理机制的最终效果是 afterExecute 和线程的 UncaughtExceptionHandler 能够尽可能准确地获得用户代码遇到的任何问题的信息。
@param w 工作线程
*/