線程池之Worker線程管理

Worker線程管理

線程池爲了掌握線程的狀態並維護線程的生命週期,設計了線程池內的工作線程Worker。我們來看一下它的部分代碼:

private final class Worker extends AbstractQueuedSynchronizer implements Runnable{
    final Thread thread;//Worker持有的線程
    Runnable firstTask;//初始化的任務,可以爲null
}

Worker這個工作線程,實現了Runnable接口,並持有一個線程thread,一個初始化的任務firstTask。thread是在調用構造方法時通過ThreadFactory來創建的線程,可以用來執行任務;firstTask用它來保存傳入的第一個任務,這個任務可以有也可以爲null。如果這個值是非空的,那麼線程就會在啓動初期立即執行這個任務,也就對應核心線程創建時的情況;如果這個值是null,那麼就需要創建一個線程去執行workQueue中的任務,也就是非核心線程的創建。

Worker執行任務的模型如下圖所示:

線程池管理線程的生命週期,需要在線程長時間不運行的時候進行回收。線程池使用一張Hash表去持有線程的引用,這樣可以通過添加引用、移除引用這樣的操作來控制線程的生命週期。這個時候重要的就是如何判斷線程是否在運行。Worker是通過繼承AQS,使用AQS來實現獨佔鎖這個功能。沒有使用可重入鎖ReentrantLock,而是使用AQS,爲的就是實現不可重入的特性去反應線程現在的執行狀態。

  1. lock方法一旦獲取了獨佔鎖,表示當前線程正在執行任務中。

  2. 如果正在執行任務,則不應該中斷線程。

  3. 如果該線程現在不是獨佔鎖的狀態,也就是空閒的狀態,說明它沒有在處理任務,這時可以對該線程進行中斷。

  4. 線程池在執行shutdown方法或tryTerminate方法時會調用interruptIdleWorkers方法來中斷空閒的線程,interruptIdleWorkers方法會使用tryLock方法來判斷線程池中的線程是否是空閒狀態;如果線程是空閒狀態則可以安全回收。

在線程回收過程中就使用到了這種特性,回收過程如下圖所示:

 Worker線程增加

增加線程是通過線程池中的addWorker方法,該方法的功能就是增加一個線程,該方法不考慮線程池是在哪個階段增加的該線程,這個分配線程的策略是在上個步驟完成的,該步驟僅僅完成增加線程,並使它運行,最後返回是否成功這個結果。addWorker方法有兩個參數:firstTask、core。firstTask參數用於指定新增的線程執行的第一個任務,該參數可以爲空;core參數爲true表示在新增線程時會判斷當前活動線程數是否少於corePoolSize,false表示新增線程前需要判斷當前活動線程數是否少於maximumPoolSize,其執行流程如下圖所示:

 Worker線程回收

線程池中線程的銷燬依賴JVM自動的回收,線程池做的工作是根據當前線程池的狀態維護一定數量的線程引用,防止這部分線程被JVM回收,當線程池決定哪些線程需要回收時,只需要將其引用消除即可。Worker被創建出來後,就會不斷地進行輪詢,然後獲取任務去執行,核心線程可以無限等待獲取任務,非核心線程要限時獲取任務。當Worker無法獲取到任務,也就是獲取的任務爲空時,循環會結束,Worker會主動消除自身在線程池內的引用。

try {
  while (task != null || (task = getTask()) != null) {
    //執行任務
  }
} finally {
  processWorkerExit(w, completedAbruptly);//獲取不到任務時,主動回收自己
}

線程回收的工作是在processWorkerExit方法完成的。

事實上,在這個方法中,將線程引用移出線程池就已經結束了線程銷燬的部分。但由於引起線程銷燬的可能性有很多,線程池還要判斷是什麼引發了這次銷燬,是否要改變線程池的現階段狀態,是否要根據新狀態,重新分配線程。

Worker線程執行任務

在Worker類中的run方法調用了runWorker方法來執行任務,執行流程如下圖所示:

大致過程如下

1、while循環不斷地通過getTask()方法獲取任務。

2、getTask()方法從阻塞隊列中取任務。

3、如果線程池正在停止,那麼要保證當前線程是中斷狀態,否則要保證當前線程不是中斷狀態。

4、執行任務。

5、如果getTask結果爲null則跳出循環,執行processWorkerExit()方法,銷燬線程。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章