Java並發編程:ThreadPoolExecutor類及方法源碼分析__jdk

來源:互聯網
上載者:User

  ThreadPoolExecutor是jdk內建線程池實作類別,現有的Executors工具類實現的幾種線程池核心都是調用ThreadPoolExecutor類。ThreadPoolExecutor在jdk1.7及以後做了部分修改,本文以JDK1.8為準1 建構函式

  ThreadPoolExecutor類共有4個建構函式,其他三個建構函式都是調用下參數最全的一個,下面只介紹參數最全的的一個。

 public ThreadPoolExecutor(int corePoolSize,  //參數的意義已經在上一篇中介紹                              int maximumPoolSize,                              long keepAliveTime,                              TimeUnit unit,                              BlockingQueue<Runnable> workQueue,                              ThreadFactory threadFactory,                              RejectedExecutionHandler handler) {        if (corePoolSize < 0 ||  //參數檢查            maximumPoolSize <= 0 ||            maximumPoolSize < corePoolSize ||            keepAliveTime < 0)            throw new IllegalArgumentException();        if (workQueue == null || threadFactory == null || handler == null)            throw new NullPointerException();        this.corePoolSize = corePoolSize; //設定基本線程數        this.maximumPoolSize = maximumPoolSize; //設定最大線程數        this.workQueue = workQueue;  //設定任務隊列        this.keepAliveTime = unit.toNanos(keepAliveTime); //設定存活時間        this.threadFactory = threadFactory; //設定線程工廠        this.handler = handler; //設局拒絕策略    }
2 ThreadPoolExecutor類的方法

  ThreadPoolExecutor類的主要方法有提交任務的execute()方法和submit()方法,終止線程的shutdown()方法和shutdowmNow方法。
  execute方法用於提交任務,在Executor介面中聲明並在ThreadPoolExecutor類中實現。
  submit方法用於提交任務並且有返回結果,在ExecutorService中聲明並且在AbstractExecutorService類中實現,ThreadPoolExecutor類並沒有重寫。
  shutdown方法用於關閉線程池,但是允許正在啟動並執行任務運行完,將狀態置為SHUTDOWN。
  shutdownNow方法在關閉線程池時嘗試終止正在啟動並執行任務,將狀態置為STOP。 3 ThreadPoolExecutor類重要方法源碼分析 3.1 execute方法源碼分析

  execute方法在JDK1.7及以後具體實現做了重大修改,分析execute源碼之前先列舉ThreadPoolExecutor類定義的一些常量。

      private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0)); //採用原子整型來記錄線程數量及狀態    private static final int COUNT_BITS = Integer.SIZE - 3;  //線程池中線程數量存在低29位,高3位是線程池狀態    private static final int CAPACITY   = (1 << COUNT_BITS) - 1;    // runState is stored in the high-order bits    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;    // Packing and unpacking ctl    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; }

  線程池的五種狀態:
  RUNNING 在ThreadPoolExecutor被執行個體化的時候就是這個狀態。
  SHUTDOWN 通常是已經執行過shutdown()方法,不再接受新任務,等待線程池中和隊列中任務完成。
  STOP 通常是已經執行過shutdownNow()方法,不接受新任務,隊列中的任務也不再執行,並嘗試終止線程池中的線程。
  TIDYING 線程池為空白,就會到達這個狀態,執行terminated()方法。
  TERMINATED terminated()執行完畢,就會到達這個狀態。
  下面直接上代碼,程式碼分析放在注釋裡:

public void execute(Runnable command) {        if (command == null) //參數檢查            throw new NullPointerException();        int c = ctl.get(); //擷取目前記錄線程池狀態和池中線程數量的變數        if (workerCountOf(c) < corePoolSize) { //如果當前線程池中線程數量小於基本線程數量            if (addWorker(command, true))  //新起一個線程處理任務,並將這個任務作為這個線程的第一個任務                return;            c = ctl.get(); //增加線程失敗,再次擷取變數。(其他線程可能改變了線程池中線程數量,線程也可能die)        }        if (isRunning(c) && workQueue.offer(command)) { //如果線程池還是RUNNING狀態就將任務加入工作隊列            int recheck = ctl.get(); //需要double check主要是時間差的問題,在上一句和這一句中間其他線程可能改變了線程池狀態            if (! isRunning(recheck) && remove(command)) //如果線程池狀態不再是RUNNING,則從工作隊列移除這個任務                reject(command); //移除任務成功,對這個任務使用拒絕策略            else if (workerCountOf(recheck) == 0) //如果線程池狀態是RUNNING,並且線程數量為0,說明基本線程數為0                addWorker(null, false); //線程池啟動一個線程,啟動後並不直接處理任務,並且判斷界限變為maximumPoolSize        }        else if (!addWorker(command, false))  //如果工作隊列已滿,則增加線程處理,線程判斷條件變為maximumPoolSize            reject(command);    }

  忽略細節後總的邏輯如下:
  第一,線程池中線程數量小於基本線程數(corePoolSize),則啟動新線程處理新的任務。
  第二,線程池中線程數不小於基本線程數,則將任務加入工作隊列。
  第三,工作隊列如果已滿,判斷線程數如果小於最大線程數(maximumPoolSize),則啟動新線程處理當前任務。
  execute方法中最核心的方法就是addWorker方法,這個方法負責建立線程,下面重點分析洗addWorker源碼。

   private boolean addWorker(Runnable firstTask, boolean core) {        retry:        for (;;) {            int c = ctl.get();            int rs = runStateOf(c); //擷取線程池狀態            // Check if queue empty only if necessary.            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;                if (compareAndIncrementWorkerCount(c)) //如果線程池的狀態和線程數量都沒有改變,則將線程數量+1並且開始真正建立線程                    break retry;                c = ctl.get();  // Re-read ctl,線程數量或者線程池狀態改變重新擷取線程狀態                if (runStateOf(c) != rs) //線程池狀態改變則重新判斷是否要建立新線程                    continue retry;                // else CAS failed due to workerCount change; retry inner loop            }        }        boolean workerStarted = false;        boolean workerAdded = false;        //private final class Worker extends AbstractQueuedSynchronizer implements Runnable        Worker w = null;        try {            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 rs = runStateOf(ctl.get());//擷取線程狀態                    if (rs < SHUTDOWN ||                        (rs == SHUTDOWN && firstTask == null)) { //檢查線程池狀態                        if (t.isAlive()) // precheck that t is startable                            throw new IllegalThreadStateException();                        workers.add(w);  //添加建立好的worker對象                        int s = workers.size();                        if (s > largestPoolSize) //更新線程池最大數量記錄                            largestPoolSize = s;                        workerAdded = true;                    }                } finally {                    mainLock.unlock();                }                if (workerAdded) {                    t.start();  //啟動線程                    workerStarted = true;                }            }        } finally {            if (! workerStarted) //線程未啟動成功,失敗處理                addWorkerFailed(w);        }        return workerStarted;    }
3.2 shutdown方法源碼分析

  shutdown方法關閉線程池時將線程池的狀態置為SHUTDOWN,不再接受新任務,等待隊列中的任務執行完成。

public void shutdown() {        final ReentrantLock mainLock = this.mainLock;        mainLock.lock();        try {            checkShutdownAccess(); //檢查當前線程是否有許可權終端線程池中的所有線程            advanceRunState(SHUTDOWN); //將線程池狀態改為SHUTDOWN            interruptIdleWorkers(); //中斷空閑線程            onShutdown(); // hook for ScheduledThreadPoolExecutor        } finally {            mainLock.unlock();        }        tryTerminate(); //將線程池狀態置為TERMINATED    }
3.3 shutdownNow方法源碼分析

  shutdownNow方法關閉線程池時將線程池的狀態置為STOP,並且停止隊列中進行中的任務。

public List<Runnable> shutdownNow() {        List<Runnable> tasks;        final ReentrantLock mainLock = this.mainLock;        mainLock.lock();        try {            checkShutdownAccess();            advanceRunState(STOP); //將線程池狀態改為STOP            interruptWorkers();            tasks = drainQueue(); //和shutdown方法的區別就在於shutdownNow會停止正在處理的任務        } finally {            mainLock.unlock();        }        tryTerminate();        return tasks;    }

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.