1. 程式人生 > >ThreadPoolExecutor原始碼分析(一):重要成員變數

ThreadPoolExecutor原始碼分析(一):重要成員變數


        ThreadPoolExecutor是一個通過使用可能幾個池執行緒之一來執行每個提交任務的ExecutorService,這些執行緒池通常通過Executors工廠方法進行配置。

        ThreadPoolExecutor中的執行緒池處理了兩個不同的問題:

        1、由於減少了每個任務呼叫的開銷,在執行大量的非同步任務時它們通常提供改進的效能;

        2、它們提供了邊界和管理資源的一種手段,包括多執行緒,在執行任務集合時的消耗。

        每個ThreadPoolExecutor還維護一些基本的統計資料,例如完成任務的數量。

        一、ThreadPoolExecutor中的重要成員變數

        1、AtomicInteger ctl

        AtomicInteger型別的ctl代表了ThreadPoolExecutor中的控制狀態,它是一個複核型別的成員變數,是一個原子整數,藉助高低位包裝了兩個概念:

        (1)workerCount:執行緒池中當前活動的執行緒數量,佔據ctl的低29位;

        (2)runState:執行緒池執行狀態,佔據ctl的高3位,有RUNNING、SHUTDOWN、STOP、TIDYING、TERMINATED五種狀態。

        AtomicInteger ctl的定義如下:

  1. privatefinal AtomicInteger ctl = 
    new AtomicInteger(ctlOf(RUNNING, 0));  

        先說下workerCount:執行緒池中當前活動的執行緒數量,它佔據ctl的低29位,這樣,每當活躍執行緒數增加或減少時,ctl直接做相應數目的增減即可,十分方便。而ThreadPoolExecutor中COUNT_BITS就代表了workerCount所佔位數,定義如下:

  1. privatestaticfinalint COUNT_BITS = Integer.SIZE - 3;  
        在Java中,一個int佔據32位,而COUNT_BITS的結果不言而喻,Integer大小32減去3,就是29;另外,既然workerCount代表了執行緒池中當前活動的執行緒數量,那麼
它肯定有個上下限閾值,下限很明顯就是0,上限呢?ThreadPoolExecutor中CAPACITY就代表了workerCount的上限,它是ThreadPoolExecutor中理論上的最大活躍執行緒數,其定義如下:
  1. private
    staticfinalint CAPACITY   = (1 << COUNT_BITS) - 1;  
        運算過程為1左移29位,也就是00000000 00000000 00000000 00000001 --> 001 0000 00000000 00000000 00000000,再減去1的話,就是 000 11111 11111111 11111111 11111111,前三位代表執行緒池執行狀態runState,所以這裡workerCount的理論最大值就應該是29個1,即536870911;

        既然workerCount作為其中一個概念複合在AtomicInteger ctl中,那麼ThreadPoolExecutor理應提供從AtomicInteger ctl中解析出workerCount的方法,如下:

  1. privatestaticint workerCountOf(int c)  { return c & CAPACITY; }  
        計算邏輯很簡單,傳入的c代表的是ctl的值,即高3位為執行緒池執行狀態runState,低29位為執行緒池中當前活動的執行緒數量workerCount,將其與CAPACITY進行與操作&,也就是與000 11111 11111111 11111111 11111111進行與操作,c的前三位通過與000進行與操作,無論c前三位為何值,最終都會變成000,也就是捨棄前三位的值,而c的低29位與29個1進行與操作,c的低29位還是會保持原值,這樣就從AtomicInteger ctl中解析出了workerCount的值。
        接下來,我們再看下runState:執行緒池執行狀態,它佔據ctl的高3位,有RUNNING、SHUTDOWN、STOP、TIDYING、TERMINATED五種狀態。我們先分別解釋下這五種狀態:

        (1)RUNNING:接受新任務,並處理佇列任務

  1. privatestaticfinalint RUNNING    = -1 << COUNT_BITS;  
        -1在Java底層是由32個1表示的,左移29位的話,即111 00000 00000000 00000000 00000000,也就是低29位全部為0,高3位全部為1的話,表示RUNNING狀態,即-536870912;

        (2)SHUTDOWN:不接受新任務,但會處理佇列任務

  1. privatestaticfinalint SHUTDOWN   =  0 << COUNT_BITS;  
        0在Java底層是由32個0表示的,無論左移多少位,還是32個0,即000 00000 00000000 00000000 00000000,也就是低29位全部為0,高3位全部為0的話,表示SHUTDOWN狀態,即0;

        (3)STOP:不接受新任務,不會處理佇列任務,而且會中斷正在處理過程中的任務

  1. privatestaticfinalint STOP       =  1 << COUNT_BITS;  

        1在Java底層是由前面的31個0和1個1組成的,左移29位的話,即001 00000 00000000 00000000 00000000,也就是低29位全部為0,高3位為001的話,表示STOP狀態,即536870912;

        (4)TIDYING:所有的任務已結束,workerCount為0,執行緒過渡到TIDYING狀態,將會執行terminated()鉤子方法

  1. privatestaticfinalint TIDYING    =  2 << COUNT_BITS;  
        2在Java底層是由前面的30個0和1個10組成的,左移29位的話,即010 00000 00000000 00000000 00000000,也就是低29位全部為0,高3位為010的話,表示TIDYING狀態,即1073741824;

        (5)TERMINATED:terminated()方法已經完成

  1. privatestaticfinalint TERMINATED =  3 << COUNT_BITS;  
        2在Java底層是由前面的30個0和1個11組成的,左移29位的話,即011 00000 00000000 00000000 00000000,也就是低29位全部為0,高3位為011的話,表示TERMINATED狀態,即1610612736;

        由上面我們可以得知,執行狀態的值按照RUNNING-->SHUTDOWN-->STOP-->TIDYING-->TERMINATED順序值是遞增的,這些值之間的數值順序很重要。隨著時間的推移,執行狀態單調增加,但是不需要經過每個狀態。那麼,可能存在的執行緒池狀態的轉換是什麼呢?如下:

        (1)RUNNING -> SHUTDOWN:呼叫shutdownNow()方法後,或者執行緒池實現了finalize方法,在裡面呼叫了shutdown方法,即隱式呼叫;

        (2)(RUNNING or SHUTDOWN) -> STOP:呼叫shutdownNow()方法後;

        (3)SHUTDOWN -> TIDYING:執行緒池和佇列均為空時;

        (4)STOP -> TIDYING:執行緒池為空時;

        (5)TIDYING -> TERMINATED:terminated()鉤子方法完成時。

        我們再來看下是實現獲取執行狀態的runStateOf()方法,程式碼如下:

  1. privatestaticint runStateOf(int c)     { return c & ~CAPACITY; }  
        ~是按位取反的意思,CAPACITY表示的是高位的3個0,和低位的29個1,而~CAPACITY則表示高位的3個1,2低位的9個0,然後再與入參c執行按位與操作,即高3位保持原樣,低29位全部設定為0,也就獲取了執行緒池的執行狀態runState。

        最後,我們再看下原子變數ctl的初始化方法ctlOf(),程式碼如下:

  1. privatestaticint ctlOf(int rs, int wc) { return rs | wc; }  
        很簡單,傳入的rs表示執行緒池執行狀態runState,其是高3位有值,低29位全部為0的int,而wc則代表執行緒池中有效執行緒的數量workerCount,其為高3位全部為0,而低29位有值得int,將runState和workerCount做或操作|處理,即用runState的高3位,workerCount的低29位填充的數字,而預設傳入的runState、workerCount分別為RUNNING和0。
        2、BlockingQueue<Runnable> workQueue

        workQueue是用於持有任務並將其轉換成工作執行緒worker的佇列;

        3、HashSet<Worker> workers

        workers是包含執行緒池中所有工作執行緒worker的集合,僅僅當擁有mainLock鎖時才能訪問它;

        4、long completedTaskCount

        completedTaskCount是已完成任務的計數器,只有在worker執行緒的終止,僅僅當擁有mainLock鎖時才能訪問它;

        5、volatile ThreadFactory threadFactory

        建立新執行緒的工廠類;

        6、volatile RejectedExecutionHandler handler

        執行過程中shutdown時呼叫的handler;

        7、volatile long keepAliveTime

        空閒執行緒等待工作的超時時間(納秒),即空閒執行緒存活時間;

        8、volatile boolean allowCoreThreadTimeOut

        預設值為false,如果為false,core執行緒在空閒時依然存活;如果為true,則core執行緒等待工作,直到時間超時至keepAliveTime;

        9、volatile int corePoolSize

        核心執行緒池大小,保持存活的工作執行緒的最小數目,當小於corePoolSize時,會直接啟動新的一個執行緒來處理任務,而不管執行緒池中是否有空閒執行緒;

        10、volatile int maximumPoolSize

        執行緒池最大大小,也就是執行緒池中執行緒的最大數量。