免费观看又色又爽又黄的小说免费_美女福利视频国产片_亚洲欧美精品_美国一级大黄大色毛片

怎樣解析完整的ThreadPoolExecutor

怎樣解析完整的ThreadPoolExecutor,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

創新互聯堅持“要么做到,要么別承諾”的工作理念,服務領域包括:做網站、成都網站設計、企業官網、英文網站、手機端網站、網站推廣等服務,滿足客戶于互聯網時代的全州網站設計、移動媒體設計的需求,幫助企業找到有效的互聯網解決方案。努力成為您成熟可靠的網絡建設合作伙伴!

ThreadPoolExecutor源碼解析

今天為了給一個朋友做一份文檔,從源碼層級解析一下ThreadPoolExecutor。然后就直接在源碼上寫備注的形式解析。

1、常用變量的解釋

// 1. `ctl`,可以看做一個int類型的數字,高3位表示線程池狀態,低29位表示worker數量
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
// 2. `COUNT_BITS`,`Integer.SIZE`為32,所以`COUNT_BITS`為29
private static final int COUNT_BITS = Integer.SIZE - 3;
// 3. `CAPACITY`,線程池允許的最大線程數。1左移29位,然后減1,即為 2^29 - 1
private static final int CAPACITY   = (1 << COUNT_BITS) - 1;

// runState is stored in the high-order bits
// 4. 線程池有5種狀態,按大小排序如下:RUNNING < SHUTDOWN < STOP < TIDYING < TERMINATED
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
// 5. `runStateOf()`,獲取線程池狀態,通過按位與操作,低29位將全部變成0
private static int runStateOf(int c)     { return c & ~CAPACITY; }
// 6. `workerCountOf()`,獲取線程池worker數量,通過按位與操作,高3位將全部變成0
private static int workerCountOf(int c)  { return c & CAPACITY; }
// 7. `ctlOf()`,根據線程池狀態和線程池worker數量,生成ctl值
private static int ctlOf(int rs, int wc) { return rs | wc; }

/*
* Bit field accessors that don't require unpacking ctl.
* These depend on the bit layout and on workerCount being never negative.
*/
// 8. `runStateLessThan()`,線程池狀態小于xx
private static boolean runStateLessThan(int c, int s) {
   return c < s;
}
// 9. `runStateAtLeast()`,線程池狀態大于等于xx
private static boolean runStateAtLeast(int c, int s) {
   return c >= s;
}

2、構造方法

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;
   // 根據傳入參數`unit`和`keepAliveTime`,將存活時間轉換為納秒存到變量`keepAliveTime `中
   this.keepAliveTime = unit.toNanos(keepAliveTime);
   this.threadFactory = threadFactory;
   this.handler = handler;
}

3、提交執行task的過程

public void execute(Runnable command) {
   if (command == null)
       throw new NullPointerException();
   /*
    * Proceed in 3 steps:
    *
    * 1. If fewer than corePoolSize threads are running, try to
    * start a new thread with the given command as its first
    * task.  The call to addWorker atomically checks runState and
    * workerCount, and so prevents false alarms that would add
    * threads when it shouldn't, by returning false.
    *
    * 2. If a task can be successfully queued, then we still need
    * to double-check whether we should have added a thread
    * (because existing ones died since last checking) or that
    * the pool shut down since entry into this method. So we
    * recheck state and if necessary roll back the enqueuing if
    * stopped, or start a new thread if there are none.
    *
    * 3. If we cannot queue task, then we try to add a new
    * thread.  If it fails, we know we are shut down or saturated
    * and so reject the task.
    */
   int c = ctl.get();
   // worker數量比核心線程數小,直接創建worker執行任務
   if (workerCountOf(c) < corePoolSize) {
       if (addWorker(command, true))
           return;
       c = ctl.get();
   }
   // worker數量超過核心線程數,任務直接進入隊列
   if (isRunning(c) && workQueue.offer(command)) {
       int recheck = ctl.get();
       // 線程池狀態不是RUNNING狀態,說明執行過shutdown命令,需要對新加入的任務執行reject()操作。
       // 這兒為什么需要recheck,是因為任務入隊列前后,線程池的狀態可能會發生變化。
       if (! isRunning(recheck) && remove(command))
           reject(command);
       // 這兒為什么需要判斷0值,主要是在線程池構造方法中,核心線程數允許為0
       else if (workerCountOf(recheck) == 0)
           addWorker(null, false);
   }
   // 如果線程池不是運行狀態,或者任務進入隊列失敗,則嘗試創建worker執行任務。
   // 這兒有3點需要注意:
   // 1. 線程池不是運行狀態時,addWorker內部會判斷線程池狀態
   // 2. addWorker第2個參數表示是否創建核心線程
   // 3. addWorker返回false,則說明任務執行失敗,需要執行reject操作
   else if (!addWorker(command, false))
       reject(command);
}

4、addworker源碼解析

private boolean addWorker(Runnable firstTask, boolean core) {
   retry:
   // 外層自旋
   for (;;) {
       int c = ctl.get();
       int rs = runStateOf(c);

       // 這個條件寫得比較難懂,我對其進行了調整,和下面的條件等價
       // (rs > SHUTDOWN) ||
       // (rs == SHUTDOWN && firstTask != null) ||
       // (rs == SHUTDOWN && workQueue.isEmpty())
       // 1. 線程池狀態大于SHUTDOWN時,直接返回false
       // 2. 線程池狀態等于SHUTDOWN,且firstTask不為null,直接返回false
       // 3. 線程池狀態等于SHUTDOWN,且隊列為空,直接返回false
       // Check if queue empty only if necessary.
       if (rs >= SHUTDOWN &&
           ! (rs == SHUTDOWN &&
              firstTask == null &&
              ! workQueue.isEmpty()))
           return false;

       // 內層自旋
       for (;;) {
           int wc = workerCountOf(c);
           // worker數量超過容量,直接返回false
           if (wc >= CAPACITY ||
               wc >= (core ? corePoolSize : maximumPoolSize))
               return false;
           // 使用CAS的方式增加worker數量。
           // 若增加成功,則直接跳出外層循環進入到第二部分
           if (compareAndIncrementWorkerCount(c))
               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;
   Worker w = null;
   try {
       w = new Worker(firstTask);
       final Thread t = w.thread;
       if (t != null) {
           final ReentrantLock mainLock = this.mainLock;
           // worker的添加必須是串行的,因此需要加鎖
           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)) {
                   // worker已經調用過了start()方法,則不再創建worker
                   if (t.isAlive()) // precheck that t is startable
                       throw new IllegalThreadStateException();
                   // worker創建并添加到workers成功
                   workers.add(w);
                   // 更新`largestPoolSize`變量
                   int s = workers.size();
                   if (s > largestPoolSize)
                       largestPoolSize = s;
                   workerAdded = true;
               }
           } finally {
               mainLock.unlock();
           }
           // 啟動worker線程
           if (workerAdded) {
               t.start();
               workerStarted = true;
           }
       }
   } finally {
       // worker線程啟動失敗,說明線程池狀態發生了變化(關閉操作被執行),需要進行shutdown相關操作
       if (! workerStarted)
           addWorkerFailed(w);
   }
   return workerStarted;
}

5、線程池worker任務單元

private final class Worker
   extends AbstractQueuedSynchronizer
   implements Runnable
{
   /**
    * This class will never be serialized, but we provide a
    * serialVersionUID to suppress a javac warning.
    */
   private static final long serialVersionUID = 6138294804551838833L;

   /** Thread this worker is running in.  Null if factory fails. */
   final Thread thread;
   /** Initial task to run.  Possibly null. */
   Runnable firstTask;
   /** Per-thread task counter */
   volatile long completedTasks;

   /**
    * Creates with given first task and thread from ThreadFactory.
    * @param firstTask the first task (null if none)
    */
   Worker(Runnable firstTask) {
       setState(-1); // inhibit interrupts until runWorker
       this.firstTask = firstTask;
       // 這兒是Worker的關鍵所在,使用了線程工廠創建了一個線程。傳入的參數為當前worker
       this.thread = getThreadFactory().newThread(this);
   }

   /** Delegates main run loop to outer runWorker  */
   public void run() {
       runWorker(this);
   }

   // 省略代碼...
}

6、核心線程執行邏輯-runworker

final void runWorker(Worker w) {
   Thread wt = Thread.currentThread();
   Runnable task = w.firstTask;
   w.firstTask = null;
   // 調用unlock()是為了讓外部可以中斷
   w.unlock(); // allow interrupts
   // 這個變量用于判斷是否進入過自旋(while循環)
   boolean completedAbruptly = true;
   try {
       // 這兒是自旋
       // 1. 如果firstTask不為null,則執行firstTask;
       // 2. 如果firstTask為null,則調用getTask()從隊列獲取任務。
       // 3. 阻塞隊列的特性就是:當隊列為空時,當前線程會被阻塞等待
       while (task != null || (task = getTask()) != null) {
           // 這兒對worker進行加鎖,是為了達到下面的目的
           // 1. 降低鎖范圍,提升性能
           // 2. 保證每個worker執行的任務是串行的
           w.lock();
           // If pool is stopping, ensure thread is interrupted;
           // if not, ensure thread is not interrupted.  This
           // requires a recheck in second case to deal with
           // shutdownNow race while clearing interrupt
           // 如果線程池正在停止,則對當前線程進行中斷操作
           if ((runStateAtLeast(ctl.get(), STOP) ||
                (Thread.interrupted() &&
                 runStateAtLeast(ctl.get(), STOP))) &&
               !wt.isInterrupted())
               wt.interrupt();
           // 執行任務,且在執行前后通過`beforeExecute()`和`afterExecute()`來擴展其功能。
           // 這兩個方法在當前類里面為空實現。
           try {
               beforeExecute(wt, task);
               Throwable thrown = null;
               try {
                   task.run();
               } catch (RuntimeException x) {
                   thrown = x; throw x;
               } catch (Error x) {
                   thrown = x; throw x;
               } catch (Throwable x) {
                   thrown = x; throw new Error(x);
               } finally {
                   afterExecute(task, thrown);
               }
           } finally {
               // 幫助gc
               task = null;
               // 已完成任務數加一
               w.completedTasks++;
               w.unlock();
           }
       }
       completedAbruptly = false;
   } finally {
       // 自旋操作被退出,說明線程池正在結束
       processWorkerExit(w, completedAbruptly);
   }
}

關于怎樣解析完整的ThreadPoolExecutor問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注創新互聯行業資訊頻道了解更多相關知識。

網頁題目:怎樣解析完整的ThreadPoolExecutor
網站地址:http://m.newbst.com/article20/ijphco.html

成都網站建設公司_創新互聯,為您提供品牌網站建設電子商務品牌網站制作標簽優化網站建設網站排名

廣告

聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯

成都網頁設計公司