ThreadPoolExecutor 杂记
When a new task is submitted in method execute(Runnable), and fewer than corePoolSize threads are running, a new thread is created to handle the request, even if other worker threads are idle.
当提交task时,如果当前线程数小于corePoolSize,那么不管当前已创建线程是否处于空闲状态,总会创建一个新线程来处理该task。
Most typically, core and maximum pool sizes are set only upon construction, but they may also be changed dynamically using setCorePoolSize and setMaximumPoolSize.
核心线程数和最大线程数都可以动态调整。
By default, even core threads are initially created and started only when new tasks arrive, but this can be overridden dynamically using method prestartCoreThread or prestartAllCoreThreads. You probably want to prestart threads if you construct the pool with a non-empty queue.
创建ThreadPoolExecutor时,默认情况下,只有当有任务提交时,才会创建核心线程。不过也可以通过prestartCoreThread和prestartAllCoreThreads提前创建线程。当构造ThreadPoolExecutor时,如果使用非空queue,这很有用。
If fewer than corePoolSize threads are running, the Executor always prefers adding a new thread rather than queuing.
如果当前线程数小于corePoolSize,会直接新增一个线程,而不是把任务加到queue中。
A pool that is no longer referenced in a program AND has no remaining threads will be shutdown automatically. If you would like to ensure that unreferenced pools are reclaimed even if users forget to call shutdown, then you must arrange that unused threads eventually die, by setting appropriate keep-alive times, using a lower bound of zero core threads and/or setting allowCoreThreadTimeOut(boolean).
如果ThreadPoolExecutor不再被引用并且其没有存活的线程,那么它可以自动关闭,如果有存活的线程,就不会关闭。如果希望线程最终可以关闭,可以设置keep-alive times,并且设置核心线程数为0或者设置allowCoreThreadTimeOut。
线程增加(a)时机:
1. 任务提交时,当前线程数小于corePoolSize
2. 任务提交时,当前线程数小于maximumPoolSize,且任务队列满
3. 任务提交时,ThreadPoolExecutor处于运行状态,任务添加到队列,随后ThreadPoolExecutor变为非运行状态,任务又未从队列移除成功,且当前没有线程存活,创建一个线程处理该任务
4. 任务提交时,ThreadPoolExecutor处于运行状态,任务添加到队列,但之前创建线程全部die,则创建一个线程处理任务
5. 当前线程运行的任务出现异常,线程死掉,创建新线程替换旧线程(线程没有任务(completedAbruptly=false)或死掉时(completedAbruptly=true)会调用processWorkerExit)
private void processWorkerExit(Worker w, boolean completedAbruptly) { if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted decrementWorkerCount(); final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { completedTaskCount += w.completedTasks; workers.remove(w); } finally { mainLock.unlock(); } tryTerminate(); int c = ctl.get(); if (runStateLessThan(c, STOP)) { if (!completedAbruptly) { int min = allowCoreThreadTimeOut ? 0 : corePoolSize; if (min == 0 && ! workQueue.isEmpty()) min = 1; if (workerCountOf(c) >= min) return; // replacement not needed } addWorker(null, false); // a5 } }
6. setCorePoolSize, prestartCoreThread, prestartAllCoreThreads, ensurePrestart被调用时
任务reject(r)时机:
1. 任务提交时,当前ThreadPoolExecutor不处于运行状态
2. 任务提交时,当前ThreadPoolExecutor处于运行状态,但队列满,且核心线程数达到maximumPoolSize
3. 任务提交时,ThreadPoolExecutor处于运行状态,任务添加到队列,随后ThreadPoolExecutor变为非运行状态,任务从队列移除成功
public void execute(Runnable command) { if (command == null) throw new NullPointerException(); int c = ctl.get(); if (workerCountOf(c) < corePoolSize) { if (addWorker(command, true)) // a1 return; c = ctl.get(); } if (isRunning(c) && workQueue.offer(command)) { int recheck = ctl.get(); if (! isRunning(recheck) && remove(command)) reject(command); // r2,r3 else if (workerCountOf(recheck) == 0) addWorker(null, false); // a3,a4 } else if (!addWorker(command, false)) // a2 reject(command); // r1 }
线程退出时机:
1. 当前线程运行的任务出现异常
2. ThreadPoolExecutor处于shutdown,且队列为空
3. ThreadPoolExecutor处于非运行态和非shutdown态
4. 没有任务时(比如,当前线程数在core和max之间,只有当队列为空时线程才会退出,否则会执行任务到没有任务时退出)
5. setCorePoolSize, allowCoreThreadTimeOut, setMaximumPoolSize, setKeepAliveTime, shutdownNow, shutdown