亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎樣解析完整的ThreadPoolExecutor

發布時間:2021-12-17 14:45:39 來源:億速云 閱讀:154 作者:柒染 欄目:大數據

怎樣解析完整的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;
}

怎樣解析完整的ThreadPoolExecutor

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問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

长岛县| 和田县| 江陵县| 丽水市| 天台县| 阳山县| 呼玛县| 徐水县| 长寿区| 抚州市| 逊克县| 庄浪县| 龙州县| 宁波市| 宜昌市| 长阳| 原平市| 福泉市| 内丘县| 太康县| 石屏县| 崇礼县| 肇东市| 苍南县| 新民市| 尤溪县| 淮安市| 文水县| 共和县| 庆阳市| 平原县| 辽源市| 侯马市| 洪江市| 宜都市| 洪洞县| 凤山县| 全椒县| 耒阳市| 泰兴市| 昆明市|