CountDownLoatch是JUC下一個用於控制計數的計數器,好比我須要從6開始計數,每一個線成運行完以後計數減一,等計數器到0時候開始執行其餘任務。java
public static void main(String[] args) throws InterruptedException { CountDownLatch countDownLatch = new CountDownLatch(6); for (int i = 0; i < 6; i++) { new Thread(() -> { System.out.println(Thread.currentThread().getName() + "\t結束"); countDownLatch.countDown(); }, String.valueOf(i)).start(); } countDownLatch.await(); System.out.println("開始執行新任務"); }
如今讓咱們來看下CountDownLoach的底層源碼函數
private static final class Sync extends AbstractQueuedSynchronizer { private static final long serialVersionUID = 4982264981922014374L; Sync(int count) { setState(count); } int getCount() { return getState(); } protected int tryAcquireShared(int acquires) { return (getState() == 0) ? 1 : -1; } protected boolean tryReleaseShared(int releases) { // Decrement count; signal when transition to zero for (;;) { int c = getState(); if (c == 0) return false; int nextc = c-1; if (compareAndSetState(c, nextc)) return nextc == 0; } } } private final Sync sync;
這裏最重要的是這個tyrReleaseShared方法,CountDownLatch也是實現了AQS機制,經過state去判斷資源知否被佔用。當咱們使用countDow函數去減1時,會觸發releaseShared方法,這個方法的參數時每次減的次數,默認是1oop
public void countDown() { sync.releaseShared(1); }
咱們點進去看看這個方法是如何實現的ui
public final boolean releaseShared(int arg) { if (tryReleaseShared(arg)) { doReleaseShared(); return true; } return false; }
這個方法調用了AQS的releaseShared,他會先去嘗試減一,判斷是否減一成功spa
protected boolean tryReleaseShared(int releases) { // Decrement count; signal when transition to zero for (;;) { int c = getState(); if (c == 0) return false; int nextc = c-1; if (compareAndSetState(c, nextc)) return nextc == 0; } }
這裏使用了CAS自旋機制對state(咱們這裏是6)進行減1,若是自旋成功就會返回true即6一個一個減最後變成0,就會執行下面的doReleaseShared方法code
private void doReleaseShared() { for (;;) { Node h = head; if (h != null && h != tail) { int ws = h.waitStatus; if (ws == Node.SIGNAL) { if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0)) continue; // loop to recheck cases unparkSuccessor(h); } else if (ws == 0 && !compareAndSetWaitStatus(h, 0, Node.PROPAGATE)) continue; // loop on failed CAS } if (h == head) // loop if head changed break; } }
這裏使用了LockSupport相關的加鎖解鎖,unpark有關這個我會在以後有空的時候進行解析,經過對AQS任務隊列進行判斷,是否只有頭節點和尾節點,這個任務隊列裏面頭節點並非真正的任務,而是爲了初始化方便操做的哨兵節點,而後對第一個任務節點進行操做,就是咱們這6步操做,每次減一做爲一個任務進行釋放(我本身認爲的)。blog
這是我第一次發帖子但願你們多多支持,準備秋招了,爭取大廠上岸,若是帖子裏有錯誤但願你們積極提出來隊列