1. 程式人生 > 實用技巧 >瞭解下JUC的執行緒池學習五(addWorker方法原始碼分析)

瞭解下JUC的執行緒池學習五(addWorker方法原始碼分析)

1.方法:boolean addWorker(Runnable firstTask, boolean core)

方法的第一的引數可以用於直接傳入任務例項,

第二個引數用於標識將要建立的工作執行緒是否核心執行緒。

2.方法原始碼

// 新增工作執行緒,如果返回false說明沒有新建立工作執行緒,如果返回true說明建立和啟動工作執行緒成功

private boolean addWorker(Runnable firstTask, boolean core) {
retry:
// 注意這是一個死迴圈 - 最外層迴圈
for (int c = ctl.get();;) {
// 這個是十分複雜的條件,這裡先拆分多個與(&&)條件:
// 1. 執行緒池狀態至少為SHUTDOWN狀態,也就是rs >= SHUTDOWN(0)
// 2. 執行緒池狀態至少為STOP狀態,也就是rs >= STOP(1),或者傳入的任務例項firstTask不為null,或者任務佇列為空
// 其實這個判斷的邊界是執行緒池狀態為shutdown狀態下,不會再接受新的任務,
//在此前提下如果狀態已經到了STOP、或者傳入任務不為空、或者任務佇列為空(已經沒有積壓任務)都不需要新增新的執行緒
if (runStateAtLeast(c, SHUTDOWN)
&& (runStateAtLeast(c, STOP)
|| firstTask != null
|| workQueue.isEmpty()))
return false;
// 注意這也是一個死迴圈 - 二層迴圈
for (;;) {
// 這裡每一輪迴圈都會重新獲取工作執行緒數wc
// 1. 如果傳入的core為true,表示將要建立核心執行緒,通過wc和corePoolSize判斷,如果wc >= corePoolSize,則返回false表示建立核心執行緒失敗
// 1. 如果傳入的core為false,表示將要創非建核心執行緒,通過wc和maximumPoolSize判斷,如果wc >= maximumPoolSize,則返回false表示建立非核心執行緒失敗
if (workerCountOf(c)
>= ((core ? corePoolSize : maximumPoolSize) & COUNT_MASK))
return false;
// 成功通過CAS更新工作執行緒數wc,則break到最外層的迴圈
if (compareAndIncrementWorkerCount(c))
break retry;
// 走到這裡說明了通過CAS更新工作執行緒數wc失敗,這個時候需要重新判斷執行緒池的狀態是否由RUNNING已經變為SHUTDOWN
c = ctl.get(); // Re-read ctl
// 如果執行緒池狀態已經由RUNNING已經變為SHUTDOWN,則重新跳出到外層迴圈繼續執行
if (runStateAtLeast(c, SHUTDOWN))
continue retry;
// 如果執行緒池狀態依然是RUNNING,CAS更新工作執行緒數wc失敗說明有可能是併發更新導致的失敗,則在內層迴圈重試即可
// else CAS failed due to workerCount change; retry inner loop
}
}
// 標記工作執行緒是否啟動成功
boolean workerStarted = false;
// 標記工作執行緒是否建立成功
boolean workerAdded = false;
Worker w = null;
try {
// 傳入任務例項firstTask建立Worker例項,Worker構造裡面會通過執行緒工廠建立新的Thread物件,所以下面可以直接操作Thread t = w.thread
// 這一步Worker例項已經建立,但是沒有加入工作執行緒集合或者啟動它持有的執行緒Thread例項
w = new Worker(firstTask);
final Thread t = w.thread;
if (t != null) {
// 這裡需要全域性加鎖,因為會改變一些指標值和非執行緒安全的集合
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// Recheck while holding lock.
// Back out on ThreadFactory failure or if
// shut down before lock acquired.
int c = ctl.get();
// 這裡主要在加鎖的前提下判斷ThreadFactory建立的執行緒是否存活或者判斷獲取鎖成功之後執行緒池狀態是否已經更變為SHUTDOWN
// 1. 如果執行緒池狀態依然為RUNNING,則只需要判斷執行緒例項是否存活,需要新增到工作執行緒集合和啟動新的Worker
// 2. 如果執行緒池狀態小於STOP,也就是RUNNING或者SHUTDOWN狀態下,同時傳入的任務例項firstTask為null,則需要新增到工作執行緒集合和啟動新的Worker
// 對於2,換言之,如果執行緒池處於SHUTDOWN狀態下,同時傳入的任務例項firstTask不為null,則不會新增到工作執行緒集合和啟動新的Worker
// 這一步其實有可能建立了新的Worker例項但是並不啟動(臨時物件,沒有任何強引用),這種Worker有可能成功下一輪GC被收集的垃圾物件
if (isRunning(c) ||
(runStateLessThan(c, STOP) && firstTask == null)) {
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
// 把建立的工作執行緒例項新增到工作執行緒集合
workers.add(w);
int s = workers.size();
// 嘗試更新歷史峰值工作執行緒數,也就是執行緒池峰值容量
if (s > largestPoolSize)
largestPoolSize = s;
// 這裡更新工作執行緒是否啟動成功標識為true,後面才會呼叫Thread#start()方法啟動真實的執行緒例項
workerAdded = true;
}
} finally {
mainLock.unlock();
}
// 如果成功新增工作執行緒,則呼叫Worker內部的執行緒例項t的Thread#start()方法啟動真實的執行緒例項
if (workerAdded) {
t.start();
// 標記執行緒啟動成功
workerStarted = true;
}
}
} finally {
// 執行緒啟動失敗,需要從工作執行緒集合移除對應的Worker
if (! workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}
// 新增Worker失敗
private void addWorkerFailed(Worker w) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// 從工作執行緒集合移除之
if (w != null)
workers.remove(w);
// wc數量減1
decrementWorkerCount();
// 基於狀態判斷嘗試終結執行緒池
tryTerminate();
} finally {
mainLock.unlock();
}
}