Java源碼分析--java.util.concurrent.ThreadPoolExecutor

聲明:該博文大部分摘自JoonWhee的博客

文章鏈接:Java併發:線程池詳解(ThreadPoolExecutor)

基礎知識

  • 進程與線程、並行與併發

    進程:每個進程都有獨立的代碼和空間,例如QQ和WeChat
    線程:程序執行運算的最小單位,在同一進程中共享資源
    併發:在同一時刻,一個cpu只能執行一個線程,但是速度快,它可以快速的在線程間切換
    並行:多個cpu同時執行一段代碼,達到真正意義上的並行

  • 線程的使用

//使用以下兩種方式,並重寫run方法:
public class MyThread extends Thread;
public class MyThread implements Runnable;
/*-------------------------------------------------------------*/
//帶返回值的線程
Callable ca2 = new Callable(){
        @Override
        public Object call() throws Exception {
            return null;
    }
};
FutureTask<String> ft2 = new FutureTask<String>(ca2);
new Thread(ft2).start();//啓動線程
ft2.get();//獲取線程返回結果,如果線程還未返回,則阻塞直至返回

線程池

/**
 * ctl低29位表示 workerCount :有效的線程數量;
 * ctl高3位表示runState:運行狀態,運行,關閉等
 */
// 初始化時有效的線程數爲0, 此時ctl爲: 1010 0000 0000 0000 0000 0000 0000 0000 
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0)); 
// 高3位用來表示運行狀態,此值用於運行狀態向左移動的位數,即29位(Integer.SIZE=32)
private static final int COUNT_BITS = Integer.SIZE - 3;     
// 線程數容量,低29位表示有效的線程數, 0001 1111 1111 1111 1111 1111 1111 1111
private static final int CAPACITY   = (1 << COUNT_BITS) - 1;

/**
 * 大小關係:RUNNING < SHUTDOWN < STOP < TIDYING < TERMINATED,
 * 源碼中頻繁使用大小關係來作爲條件判斷。
 * 1010 0000 0000 0000 0000 0000 0000 0000 運行
 * 0000 0000 0000 0000 0000 0000 0000 0000 關閉
 * 0010 0000 0000 0000 0000 0000 0000 0000 停止
 * 0100 0000 0000 0000 0000 0000 0000 0000 整理
 * 0110 0000 0000 0000 0000 0000 0000 0000 終止
 */
private static final int RUNNING    = -1 << COUNT_BITS; // 運行
private static final int SHUTDOWN   =  0 << COUNT_BITS; // 關閉
private static final int STOP       =  1 << COUNT_BITS; // 停止
private static final int TIDYING    =  2 << COUNT_BITS; // 整理
private static final int TERMINATED =  3 << COUNT_BITS; // 終止

/**
 * 功能:獲取運行狀態
 * @param c:ctl值
 * @return runState(運行狀態)
 */
private static int runStateOf(int c)     { return c & ~CAPACITY; }  
/**
 * 功能:獲取當前線程數量
 * @param c:ctl值
 * @return:workerCount(當前線程數量)
 */
private static int workerCountOf(int c)  { return c & CAPACITY; }   
/**
 * 功能:獲取ctl值
 * @param rs:運行狀態值(runState)
 * @param wc:當前線程數量(workerCount)
 */
private static int ctlOf(int rs, int wc) { return rs | wc; }    

// 狀態c是否小於s
private static boolean runStateLessThan(int c, int s) { 
    return c < s;
}
// 狀態c是否大於等於s
private static boolean runStateAtLeast(int c, int s) {
    return c >= s;
}
// 狀態c是否爲RUNNING(小於SHUTDOWN的狀態只有RUNNING)
private static boolean isRunning(int c) {
    return c < SHUTDOWN;
}

// 使用CAS增加一個有效的線程
private boolean compareAndIncrementWorkerCount(int expect) {    
    return ctl.compareAndSet(expect, expect + 1);
}

// 使用CAS減少一個有效的線程
private boolean compareAndDecrementWorkerCount(int expect) {    
    return ctl.compareAndSet(expect, expect - 1);
}

// 減少一個有效的線程
private void decrementWorkerCount() {
    do {} while (! compareAndDecrementWorkerCount(ctl.get()));
}

/** 工作隊列:
  * ArrayBlockingQueue:列表形式的工作隊列,必須要有初始隊列大小,有界隊列,先進先出。
  * LinkedBlockingQueue:鏈表形式的工作隊列,可以選擇設置初始隊列大小,有界/無界隊列,先進先出。
  * SynchronousQueue:SynchronousQueue不是一個真正的隊列,而是一種在線程之間移交的機制。要將一個元素放入SynchronousQueue中, 必須有另一個線程正在等待接受這個元素. 如果沒有線程等待,並且線程池的當前大小小於最大值,那麼ThreadPoolExecutor將創建 一個線程, 否則根據飽和策略,這個任務將被拒絕。使用直接移交將更高效,因爲任務會直接移交給執行它的線程,而不是被首先放在隊列中, 然後由工作者線程從隊列中提取任務。只有當線程池是無解的或者可以拒絕任務時,SynchronousQueue纔有實際價值。
  * PriorityBlockingQueue:優先級隊列,有界隊列,根據優先級來安排任務,任務的優先級是通過自然順序或Comparator(如果任務實現了Comparator)來定義的。
  * DelayedWorkQueue:延遲的工作隊列,無界隊列。
  */
private final BlockingQueue<Runnable> workQueue;    

// 鎖
private final ReentrantLock mainLock = new ReentrantLock(); 

// 包含線程池中的所有工作線程,只有在mainLock的情況下才能訪問,Worker集合
private final HashSet<Worker> workers = new HashSet<Worker>();

private final Condition termination = mainLock.newCondition();

// 跟蹤線程池的最大到達大小,僅在mainLock下訪問
private int largestPoolSize;

// 總的完成的任務數
private long completedTaskCount;

/**
  * 線程工廠,用於創建線程
  * DefaultThreadFactory:默認線程工廠,創建一個新的、非守護的線程,並且不包含特殊的配置信息。
  * PrivilegedThreadFactory:通過這種方式創建出來的線程,將與創建privilegedThreadFactory的線程擁有相同的訪問權限、 AccessControlContext、ContextClassLoader。如果不使用privilegedThreadFactory, 線程池創建的線程將從在需要新線程時調用execute或submit的客戶程序中繼承訪問權限。
  * 自定義線程工廠:可以自己實現ThreadFactory接口來定製自己的線程工廠方法。
  */
private volatile ThreadFactory threadFactory;

/**
  * (飽和)拒絕策略
  * AbortPolicy:中止策略。默認的飽和策略,拋出未檢查的RejectedExecutionException。調用者可以捕獲這個異常,然後根據需求編寫自己的處理代碼。
  * DiscardPolicy:拋棄策略。當新提交的任務無法保存到隊列中等待執行時,該策略會悄悄拋棄該任務。
  * DiscardOldestPolicy:拋棄最舊的策略。當新提交的任務無法保存到隊列中等待執行時,則會拋棄下一個將被執行的任務,然後嘗試重新提交新的任務。(如果工作隊列是一個優先隊列,那麼“拋棄最舊的”策略將導致拋棄優先級最高的任務,因此最好不要將“拋棄最舊的”策略和優先級隊列放在一起使用)。
  * CallerRunsPolicy:調用者運行策略。該策略實現了一種調節機制,該策略既不會拋棄任務,也不會拋出異常,而是將某些任務回退到調用者(調用線程池執行任務的主線程),從而降低新任務的流程。
  *    它不會在線程池的某個線程中執行新提交的任務,而是在一個調用了execute的線程中執行該任務。當線程池的所有線程都被佔用,並且工作隊列被填滿後,下一個任務會在調用execute時在主線程中執行(調用線程池執行任務的主線程)。
  *    由於執行任務需要一定時間,因此主線程至少在一段時間內不能提交任務,從而使得工作者線程有時間來處理完正在執行的任務。在這期間,主線程不會調用accept,因此到達的請求將被保存在TCP層的隊列中。如果持續過載,那麼TCP層將最終發現它的請求隊列被填滿,因此同樣會開始拋棄請求。
  *    當服務器過載後,這種過載情況會逐漸向外蔓延開來——從線程池到工作隊列到應用程序再到TCP層,最終達到客戶端,導致服務器在高負載下實現一種平緩的性能降低。
  */
private volatile RejectedExecutionHandler handler;

/**
 * 線程超時時間,當線程數超過corePoolSize時生效, 
 * 如果有線程空閒時間超過keepAliveTime, 則會被終止
 */
private volatile long keepAliveTime;    

// 是否允許核心線程超時,默認false,false情況下核心線程會一直存活。
private volatile boolean allowCoreThreadTimeOut;

// 核心線程數:當前線程池中線程數小於corePoolSize時,即使有線程空閒,依然創建新的線程執行任務
private volatile int corePoolSize;

// 最大線程數
private volatile int maximumPoolSize;

// 默認飽和策略(拒絕策略), 拋異常
private static final RejectedExecutionHandler defaultHandler = 
    new AbortPolicy();

private static final RuntimePermission shutdownPerm =
    new RuntimePermission("modifyThread");

/**
 * Worker類,每個Worker包含一個線程、一個初始任務、一個任務計算器
 */
private final class Worker   
    extends AbstractQueuedSynchronizer
    implements Runnable
{
    private static final long serialVersionUID = 6138294804551838833L;

    final Thread thread;    // Worker對應的線程
    Runnable firstTask; // 運行的初始任務。
    volatile long completedTasks;   // 每個線程的任務計數器

    Worker(Runnable firstTask) {
        setState(-1); // 禁止中斷,直到runWorker
        this.firstTask = firstTask; // 設置爲初始任務
        // 使用當前線程池的線程工廠創建一個線程
        this.thread = getThreadFactory().newThread(this);  
    }

    // 將主運行循環委託給外部runWorker
    public void run() {
        runWorker(this);
    }

    // Lock methods
    //
    // The value 0 represents the unlocked state.
    // The value 1 represents the locked state.
    /**
     * 通過AQS的同步狀態來實現鎖機制。state爲0時代表鎖未被獲取(解鎖狀態),
     * state爲1時代表鎖已經被獲取(加鎖狀態)。
     */
    protected boolean isHeldExclusively() { // 
        return getState() != 0; 
    }
    protected boolean tryAcquire(int unused) {  // 嘗試獲取鎖
        if (compareAndSetState(0, 1)) { // 使用CAS嘗試將state設置爲1,即嘗試獲取鎖
            // 成功將state設置爲1,則當前線程擁有獨佔訪問權
            setExclusiveOwnerThread(Thread.currentThread());    
            return true;
        }
        return false;
    }
    protected boolean tryRelease(int unused) {  // 嘗試釋放鎖
        setExclusiveOwnerThread(null);  // 釋放獨佔訪問權:即將獨佔訪問線程設爲null
        setState(0);    // 解鎖:將state設置爲0
        return true;
    }
    public void lock()        { acquire(1); }   // 加鎖
    public boolean tryLock()  { return tryAcquire(1); } // 嘗試加鎖
    public void unlock()      { release(1); }   // 解鎖
    public boolean isLocked() { return isHeldExclusively(); }  // 是否爲加鎖狀態 
    void interruptIfStarted() { // 如果線程啓動了,則進行中斷
        Thread t;
        if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
            try {
                t.interrupt();
            } catch (SecurityException ignore) {
            }
        }
    }
}
  • 工作機制
  1. 默認情況下,創建完線程池後並不會立即創建線程, 而是等到有任務提交時纔會 創建線程來進行處理。(除非調用prestartCoreThread或prestartAllCoreThreads方法)
  2. 當線程數小於核心線程數時,每提交一個任務就創建一個線程來執行,即使當前有線程處於空閒狀態,直到當前線程數達到核心線程數。
  3. 當前線程數達到核心線程數時,如果這個時候還提交任務,這些任務會被放到隊列裏,等到線程處理完了手頭的任務後,會來隊列中取任務處理。
  4. 當前線程數達到核心線程數並且隊列也滿了,如果這個時候還提交任務,則會繼續創建線程來處理,直到線程數達到最大線程數。
  5. 當前線程數達到最大線程數並且隊列也滿了,如果這個時候還提交任務,則會觸發飽和策略。
  6. 如果某個線程的控線時間超過了keepAliveTime,那麼將被標記爲可回收的,並且當前線程池的當前大小超過了核心線程數時,這個線程將被終止。
  • 一些方法
// 使用submit提交時,會運行該方法
public void execute(Runnable command) {
    if (command == null)    // 爲空校驗
        throw new NullPointerException();

    int c = ctl.get();  // 拿到當前的ctl值
    if (workerCountOf(c) < corePoolSize) {  // 如果有效的線程數小於核心線程數
        if (addWorker(command, true))   // 則新建一個線程來處理任務(核心線程還不夠,創建核心線程)
            return;
        c = ctl.get();  // 拿到當前的ctl值
    }
    // 走到這裏說明有效的線程數已經 >= 核心線程數
    if (isRunning(c) && workQueue.offer(command)) {// 如果當前狀態是運行, 嘗試將任務放入工作隊列
        int recheck = ctl.get();    // 再次拿到當前的ctl值
        // 如果再次檢查狀態不是運行, 則將剛纔添加到工作隊列的任務移除
        if (! isRunning(recheck) && remove(command)) 
            reject(command);    // 並調用拒絕策略
        else if (workerCountOf(recheck) == 0) // 如果再次檢查時,有效的線程數爲0, 
            addWorker(null, false); // 則新建一個線程(核心線程已滿,創建非核心線程)
    }
    // 走到這裏說明工作隊列已滿
    else if (!addWorker(command, false))//嘗試新建一個線程來處理任務(非核心)
        reject(command);    // 如果失敗則調用拒絕策略
}


/**
 * 添加一個Worker,Worker包含一個線程和一個任務,由這個線程來執行該任務。
 */
private boolean addWorker(Runnable firstTask, boolean core) {   
    retry:
    for (;;) {
        int c = ctl.get();  // c賦值爲ctl
        int rs = runStateOf(c); // rs賦值爲運行狀態
        /**
         * 1.如果池停止或有資格關閉,則此方法返回false;
         * 如果線程工廠在被詢問時未能創建線程,它也返回false。 
         * 包括以下5種情況:
         * 1).rs爲RUNNING,通過校驗。
         * 2).rs爲STOP或TIDYING或TERMINATED,返回false。
         * (STOP、TIDYING、TERMINATED:已經停止進入最後清理終止,不接受任務不處理隊列任務)
         * 3).rs爲SHUTDOWN,提交的任務不爲空,返回false。
         * (SHUTDOWN:不接受任務但是處理隊列任務,因此任務不爲空返回false)
         * 4).rs爲SHUTDOWN,提交的任務爲空,並且工作隊列爲空,返回false。
         * (狀態爲SHUTDOWN、提交的任務爲空、工作隊列爲空,則線程池有資格關閉,直接返回false)
         * 5).rs爲SHUTDOWN,提交的任務爲空,並且工作隊列不爲空,通過校驗。
         * (因爲SHUTDOWN狀態下剛好可以處理隊列任務)
         * ps:shutdown可以看作一個緩衝期,在此期間內,不再接任務,等待手裏的任務結束後關門
         */
        if (rs >= SHUTDOWN &&
            ! (rs == SHUTDOWN &&
               firstTask == null &&
               ! workQueue.isEmpty()))
            return false;

        for (;;) {
            int wc = workerCountOf(c);  // 拿到有效的線程數
            // 校驗有效的線程數是否超過閾值
            if (wc >= CAPACITY ||
                wc >= (core ? corePoolSize : maximumPoolSize))
                return false;
            // 使用CAS將workerCount+1, 修改成功則跳出循環,否則進入下面的狀態判斷
            if (compareAndIncrementWorkerCount(c))
                break retry;
            c = ctl.get();  // 重新讀取ctl
            // 判斷當前運行狀態,如果不等於上面獲取的運行狀態rs,
            // 說明rs被其他線程修改了,跳到retry重新校驗線程池狀態
            if (runStateOf(c) != rs)
                continue retry;
            // 走到這裏說明compareAndIncrementWorkerCount失敗; 
            // 重試內部循環(狀態沒變,則繼續內部循環,嘗試使用CAS修改workerCount)
        }
    }

    boolean workerStarted = false;  // Worker的線程是否啓動
    boolean workerAdded = false;    // Worker是否成功增加
    Worker w = null;
    try {
        w = new Worker(firstTask);  // 用firstTask和當前線程創建一個Worker
        final Thread t = w.thread;  // 拿到Worker對應的線程
        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 rs = runStateOf(ctl.get()); // 加鎖的情況下重新獲取當前的運行狀態

                // 如果當前的運行狀態爲RUNNING,
                // 或者當前的運行狀態爲SHUTDOWN並且firstTask爲空,則通過校驗
                if (rs < SHUTDOWN ||
                    (rs == SHUTDOWN && firstTask == null)) {
                    if (t.isAlive())    // 預先校驗線程是可以啓動的
                        throw new IllegalThreadStateException();
                    workers.add(w); // 將剛創建的worker添加到工作者列表
                    int s = workers.size();
                    if (s > largestPoolSize)
                        largestPoolSize = s;
                    workerAdded = true;
                }
            } finally {
                mainLock.unlock();
            }
            if (workerAdded) {  // 如果Worker添加成功,則啓動線程執行
                t.start();
                workerStarted = true;
            }
        }
    } finally {
        if (! workerStarted)    // 如果Worker的線程沒有成功啓動
            addWorkerFailed(w); // 則進行回滾, 移除之前添加的Worker
    }
    return workerStarted;
}


/**
 * Rolls back the worker thread creation.
 * - removes worker from workers, if present
 * - decrements worker count
 * - rechecks for termination, in case the existence of this
 *   worker was holding up termination
 */
private void addWorkerFailed(Worker w) {    // 回滾Worker的添加,就是將Worker移除
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        if (w != null)
            workers.remove(w);  // 移除Worker
        decrementWorkerCount(); // 有效線程數-1
        tryTerminate(); // 有worker線程移除,可能是最後一個線程退出需要嘗試終止線程池
    } finally {
        mainLock.unlock();
    }
}

/**
 * Worker的線程開始執行任務
 */
final void runWorker(Worker w) {
    Thread wt = Thread.currentThread(); // 獲取當前線程
    Runnable task = w.firstTask;    // 拿到Worker的初始任務
    w.firstTask = null;
    w.unlock(); // allow interrupts
    boolean completedAbruptly = true;   // Worker是不是因異常而死亡
    try {
        while (task != null || (task = getTask()) != null) {// Worker取任務執行,第一執行自己的firstTask,之後從隊列中拿task,直至getTask返回null
            w.lock();   // 加鎖
            /**如果線程池停止,確保線程中斷; 如果不是,確保線程不被中斷。
             * 在第二種情況下進行重新檢查,以便在清除中斷的同時處理shutdownNow競爭
             * 線程池停止指運行狀態爲STOP/TIDYING/TERMINATED中的一種
             */
            if ((runStateAtLeast(ctl.get(), STOP) ||    // 判斷線程池運行狀態
                 (Thread.interrupted() &&   // 重新檢查
                  runStateAtLeast(ctl.get(), STOP))) && // 再次判斷線程池運行狀態
                !wt.isInterrupted())// 走到這裏代表線程池運行狀態爲停止,檢查wt是否中斷
                wt.interrupt(); // 線程池的狀態爲停止並且wt不爲中斷, 則將wt中斷
            try {
                beforeExecute(wt, task);// 執行beforeExecute(默認空,需要自己重寫)
                Throwable thrown = null;
                try {
                    task.run(); // 執行任務
                } catch (RuntimeException x) {
                    thrown = x; throw x; //如果拋異常,則completedAbruptly爲true
                } catch (Error x) {
                    thrown = x; throw x;
                } catch (Throwable x) {
                    thrown = x; throw new Error(x);
                } finally {
                    afterExecute(task, thrown);// 執行afterExecute(需要自己重寫)
                }
            } finally {
                task = null;    // 將執行完的任務清空
                w.completedTasks++; // Worker完成任務數+1
                w.unlock();
            }
        }
        completedAbruptly = false;  // 如果執行到這裏,則worker是正常退出
    } finally {
        processWorkerExit(w, completedAbruptly);// 調用processWorkerExit方法
    }
}

/**
  * 返回null的情況:當前線程可以被移除 && keepAliveTime時間內獲取不到任務
  */
private Runnable getTask() {    // Worker從工作隊列獲取任務
    boolean timedOut = false; // poll方法取任務是否超時

    for (;;) {  // 無線循環
        int c = ctl.get();  // ctl
        int rs = runStateOf(c); // 當前運行狀態

        // 如果線程池運行狀態爲停止,或者可以停止(狀態爲SHUTDOWN並且隊列爲空)
        // 則返回null,代表當前Worker需要移除
        if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {    
            decrementWorkerCount(); // 將workerCount - 1
            // 返回null前將workerCount - 1,
            // 因此processWorkerExit中completedAbruptly=false時無需再減
            return null;
        }

        int wc = workerCountOf(c);  // 當前的workerCount

        /** 
          * 判斷當前線程有無超時時間(即是否可以被移除)
          * 如果 allowCoreThreadTimeOut = True:所有線程都有超時時間
          * 如果 workerCount > corePoolSize:當前線程是有超時時間的
          */ 
        boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;    

        // 如果wc超過最大線程數 或者 當前線程會超時並且已經超時,
        // 並且wc > 1 或者 工作隊列爲空,則返回null,代表當前Worker需要移除
        if ((wc > maximumPoolSize || (timed && timedOut))
            && (wc > 1 || workQueue.isEmpty())) {   // 確保有Worker可以移除 
            if (compareAndDecrementWorkerCount(c))
                // 返回null前將workerCount - 1,
                // 因此processWorkerExit中completedAbruptly=false時無需再減
                return null;    
            continue;
        }

        try {
            // 根據線程是否會超時調用相應的方法,poll爲帶超時的獲取任務方法,keepAliveQueue時間內獲取不到任務,就返回null
            // take()爲不帶超時的獲取任務方法,會 一直阻塞 直到獲取到任務
            Runnable r = timed ? 
                workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                workQueue.take();
            if (r != null)
                return r;
            timedOut = true;    // 走到這代表當前線程獲取任務超時
        } catch (InterruptedException retry) {
            timedOut = false;   // 被中斷
        }
    }
}


private void processWorkerExit(Worker w, boolean completedAbruptly) {   // Worker的退出
    // 如果Worker是異常死亡(completedAbruptly=true),則workerCount-1;
    // 如果completedAbruptly爲false的時候(正常超時退出),則代表task=getTask()等於null,
    // getTask()方法中返回null的地方,都已經將workerCount - 1,所以此處無需再-1
    if (completedAbruptly) 
        decrementWorkerCount();

    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();    // 加鎖
    try {
        completedTaskCount += w.completedTasks; // 該Worker完成的任務數加到總完成的任務數
        workers.remove(w);  // 移除該Worker
    } finally {
        mainLock.unlock();
    }

    tryTerminate(); // 有Worker線程移除,可能是最後一個線程退出,需要嘗試終止線程池

    int c = ctl.get();  // 獲取當前的ctl
    if (runStateLessThan(c, STOP)) {  // 如果線程池的運行狀態還沒停止(RUNNING或SHUTDOWN)
        if (!completedAbruptly) {   // 如果Worker不是異常死亡
            // min爲線程池的理論最小線程數:如果允許核心線程超時則min爲0,否則min爲核心線程數
            int min = allowCoreThreadTimeOut ? 0 : corePoolSize;    
            // 如果min爲0,工作隊列不爲空,將min設置爲1,確保至少有1個Worker來處理隊列裏的任務 
            if (min == 0 && ! workQueue.isEmpty())
                min = 1;
            // 當前有效的線程數>=min,直接返回;
            if (workerCountOf(c) >= min)
                return; // replacement not needed 
            // 如果代碼走到這邊,代表workerCountOf(c) < min,此時會走到下面的addWorker方法。
            // 通過getTask方法我們知道,當allowCoreThreadTimeOut爲false
            // 並且workerCount<=corePoolSize時,是不會走到processWorkerExit方法的。
            // 因此走到這邊只可能是當前移除的Worker是最後一個Worker,但是此時工作
            // 隊列還不爲空,因此min被設置成了1,所以需要在添加一個Worker來處理工作隊列。
        }
        addWorker(null, false); // 添加一個Worker
    }
}


final void tryTerminate() { // 嘗試終止線程池
    for (;;) {
        int c = ctl.get();
        // 只有當前狀態爲STOP 或者 SHUTDOWN並且隊列爲空,纔會嘗試整理並終止
        // 1: 當前狀態爲RUNNING,則不嘗試終止,直接返回
        // 2: 當前狀態爲TIDYING或TERMINATED,代表有其他線程正在執行終止,直接返回
        // 3: 當前狀態爲SHUTDOWN 並且 workQueue不爲空,則不嘗試終止,直接返回
        if (isRunning(c) || // 1
            runStateAtLeast(c, TIDYING) ||  // 2
            (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))   // 3
            return;
        // 走到這代表線程池可以終止(通過上面的校驗)
        // 如果此時有效線程數不爲0, 將中斷一個空閒的Worker,以確保關閉信號傳播
        if (workerCountOf(c) != 0) { // Eligible to terminate 
            interruptIdleWorkers(ONLY_ONE);
            return;
        }

        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();    // 加鎖,終止線程池
        try {
            // 使用CAS將ctl的運行狀態設置爲TIDYING,有效線程數設置爲0
            if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {  
                try {
                    terminated();   // 供用戶重寫的terminated方法,默認爲空
                } finally {
                    // 將ctl的運行狀態設置爲TERMINATED,有效線程數設置爲0
                    ctl.set(ctlOf(TERMINATED, 0));  
                    termination.signalAll();
                }
                return;
            }
        } finally {
            mainLock.unlock();
        }
        // else retry on failed CAS
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章