線程池的工作原理,以及拒絕策略,大家都很熟悉,下面主要講一下線程池shutdown的原理,以及一些不常用操作的原理。
shutdown
public void shutdown() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
advanceRunState(SHUTDOWN);
interruptIdleWorkers();
onShutdown(); // hook for ScheduledThreadPoolExecutor
} finally {
mainLock.unlock();
}
tryTerminate();
}
複製代碼
啓動有序關閉,在該關閉中執行先前提交的任務,但不接受任何新任務。如果已關閉,則調用不會產生任何其他影響。此方法不等待先前提交的任務完成執行。使用awaitTermination可以做到這一點。
advanceRunState
private void advanceRunState(int targetState) {
for (;;) {
int c = ctl.get();
if (runStateAtLeast(c, targetState) ||
ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c))))
break;
}
}
複製代碼
將runState轉換爲給定狀態,或者已經存在的狀態比給定狀態大時將直接返回。 循環使用CAS設置狀態,設置成功返回。
interruptIdleWorkers
private void interruptIdleWorkers(boolean onlyOne) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
for (Worker w : workers) {
Thread t = w.thread;
if (!t.isInterrupted() && w.tryLock()) {
try {
t.interrupt();
} catch (SecurityException ignore) {
} finally {
w.unlock();
}
}
if (onlyOne)
break;
}
} finally {
mainLock.unlock();
}
}
複製代碼
因爲work每次執行任務的時候都會先lock,完成任務後unlock, 如果tryLock可以成功說明work當前沒有在執行任務。使用interrupt中斷空閒的work線程。
tryTerminate
final void tryTerminate() {
for (;;) {
int c = ctl.get();
if (isRunning(c) ||
runStateAtLeast(c, TIDYING) ||
(runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
return;
if (workerCountOf(c) != 0) { // Eligible to terminate
interruptIdleWorkers(ONLY_ONE);
return;
}
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
try {
terminated();
} finally {
ctl.set(ctlOf(TERMINATED, 0));
termination.signalAll();
}
return;
}
} finally {
mainLock.unlock();
}
// else retry on failed CAS
}
}
複製代碼
shutdownNow
public List<Runnable> shutdownNow() {
List<Runnable> tasks;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
advanceRunState(STOP);
interruptWorkers();
tasks = drainQueue();
} finally {
mainLock.unlock();
}
tryTerminate();
return tasks;
}
複製代碼
嘗試停止所有正在執行的任務,暫停正在等待的任務的處理,並返回正在等待執行的任務的列表。從此方法返回後,這些任務將從任務隊列中耗盡(刪除)。此方法不等待主動執行的任務終止。除了盡最大努力嘗試停止處理正在執行的任務之外,沒有任何保證。此實現通過中斷取消任務,因此任何無法響應中斷的任務都可能永遠不會終止。
interruptWorkers
private void interruptWorkers() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
for (Worker w : workers)
w.interruptIfStarted();
} finally {
mainLock.unlock();
}
}
複製代碼
中斷所有線程,即使處於活動狀態也是如此。
drainQueue
private List<Runnable> drainQueue() {
BlockingQueue<Runnable> q = workQueue;
ArrayList<Runnable> taskList = new ArrayList<Runnable>();
q.drainTo(taskList);
if (!q.isEmpty()) {
for (Runnable r : q.toArray(new Runnable[0])) {
if (q.remove(r))
taskList.add(r);
}
}
return taskList;
}
複製代碼
使用drainTo方法將任務隊列寫入新列表。但是,如果隊列是DelayQueue或其他類型的隊列,但poll或drainTo可能無法刪除某些元素,則將它們逐個刪除。
Worker
Worker主要維護運行任務線程的中斷控制狀態,以及其他次要簿記。此類擴展了AbstractQueuedSynchronizer,以簡化獲取和釋放圍繞每個任務執行的鎖。我們實現了一個簡單的非可重入互斥鎖,而不是使用ReentrantLock,因爲我們不希望輔助任務在調用諸如setCorePoolSize之類的池控制方法時能夠重新獲取該鎖。另外,爲了抑制直到線程真正開始運行任務之前的中斷,我們將鎖定狀態初始化爲負值,並在啓動時將其清除(在runWorker中)。
runWorker
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // allow interrupts
boolean completedAbruptly = true;
try {
while (task != null || (task = getTask()) != null) {
w.lock();
// If pool is stopping, ensure thread is interrupted;
// if not, ensure thread is not interrupted. This
// requires a recheck in second case to deal with
// shutdownNow race while clearing interrupt
if ((runStateAtLeast(ctl.get(), STOP) ||
(Thread.interrupted() &&
runStateAtLeast(ctl.get(), STOP))) &&
!wt.isInterrupted())
wt.interrupt();
try {
beforeExecute(wt, task);
Throwable thrown = null;
try {
task.run();
} catch (RuntimeException x) {
thrown = x; throw x;
} catch (Error x) {
thrown = x; throw x;
} catch (Throwable x) {
thrown = x; throw new Error(x);
} finally {
afterExecute(task, thrown);
}
} finally {
task = null;
w.completedTasks++;
w.unlock();
}
}
completedAbruptly = false;
} finally {
processWorkerExit(w, completedAbruptly);
}
}
複製代碼
Work反覆從隊列中獲取任務並執行它們,同時解決許多問題:
- 我們可能從一個初始任務開始,在這種情況下,我們不需要第一個。否則,只要池是 運行時,我們從getTask獲得任務。如果返回null,則 Work由於池狀態或配置參數更改而退出。其他退出是由於引發異常 外部代碼,在這種情況下,completedAbruptly爲true,其通常導致processWorkerExit替換此線程。
- 在運行任何任務之前,先獲取鎖以防止在執行任務時其他池中斷,然後我們確保除非池正在停止,否則此線程沒有它的interrupt set。
- 在每次運行任務之前,都要調用beforeExecute,可能會引發異常,在這種情況下,我們導致線程死亡(中斷循環,使用completelyAbruptly爲true)無需處理 任務。
- 假設beforeExecute正常完成,我們運行 任務,收集其拋出的任何異常以發送給afterExecute。 我們分別處理RuntimeException,Error(兩者 規範保證我們可以捕獲)和任意Throwables。 因爲我們無法在Runnable.run中拋出Throwables,所以我們 將它們包裝在錯誤的出路(到線程的 UncaughtExceptionHandler)。 任何拋出的異常也保守地導致線程死亡。
- task.run完成後,我們調用afterExecute,這可能也會引發異常,這也會導致線程 死。 根據JLS Sec 14.20,此例外是即使task.run拋出也將有效。
- 異常機制的net效果是afterExecute和線程的UncaughtExceptionHandler具有相同的精度 我們可以提供的有關以下方面遇到的任何問題的信息用戶代碼。
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(); // shutdown狀態時,每個工作線程完成工作後,終止線程池
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); // 工作線程執行任務異常退出時,重新啓動一個工作線程來完成任務
}
}
複製代碼
線程池的狀態
線程池的控制狀態ctl是一個atomic integer。表示workCount和runState兩個字段。
workerCount指示有效線程數。int的後29位表示有效線程數。
runState,指示是否正在運行,正在關閉等。int的前三位表示線程池的狀態。
- RUNNING: 接受新任務並處理排隊的任務
- SHUTDOWN: 不接受新任務,而是處理排隊的任務
- STOP: 不接受新任務,不處理排隊任務以及中斷進行中的任務
- TIDYING: 所有任務已終止,workerCount爲零,線程轉換爲狀態TIDYING將運行Terminated()掛鉤方法
- TERMINATED: terminated()執行完成
運行狀態切換
- RUNNING -> SHUTDOWN: 在調用shutdown()時,可能隱式在finalize()中
- (RUNNING or SHUTDOWN) -> STOP: 調用shutdownNow()
- SHUTDOWN -> TIDYING: 隊列和work pool爲空
- STOP -> TIDYING: work pool爲空
- TIDYING -> TERMINATED: terminated()執行完成
狀態相關的一些代碼
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static int runStateOf(int c) { return c & ~CAPACITY; }
private static int workerCountOf(int c) { return c & CAPACITY; }
private static int ctlOf(int rs, int wc) { return rs | wc; }
private static boolean runStateLessThan(int c, int s) {
return c < s;
}
private static boolean runStateAtLeast(int c, int s) {
return c >= s;
}
private static boolean isRunning(int c) {
return c < SHUTDOWN;
}
private static final int COUNT_BITS = Integer.SIZE - 3; // 29,11101
private static final int CAPACITY = (1 << COUNT_BITS) - 1; // 29位,全是1,值 536870911
private static final int RUNNING = -1 << COUNT_BITS; // 32位,前三位是1, 值 -536870912
private static final int SHUTDOWN = 0 << COUNT_BITS; // 值 0
private static final int STOP = 1 << COUNT_BITS; // 30位,第一位是1,值 536870912
private static final int TIDYING = 2 << COUNT_BITS; // 31位,第一位是1,值 1073741824
private static final int TERMINATED = 3 << COUNT_BITS; // 31位,前兩位是1, 值 1610612736
-1 // 11111111111111111111111111111111, 32位
0 // 0
1 // 1
2 // 10
3 // 11
~CAPACITY // 32位,前三位是1,11100000000000000000000000000000,值-536870912