CountDownLatch源碼分析

實例代碼

public static void main(String[] args) throws InterruptedException {
    ExecutorService executorService = Executors.newFixedThreadPool(3);
    //規(guī)定幾步
    CountDownLatch countDownLatch = new CountDownLatch(3);//構(gòu)造函數(shù)
    executorService.submit(()->{
        System.out.println("飯煮好了");
        countDownLatch.countDown();
    });
    executorService.submit(()->{
        System.out.println("菜炒好了");
        countDownLatch.countDown();
    });
    executorService.submit(()->{
        System.out.println("湯煮好了");
        countDownLatch.countDown();
    });
    countDownLatch.await();
    //只有上面規(guī)定幾步都執(zhí)行完成了才會執(zhí)行下面語句武鲁,否則繼續(xù)等待
    System.out.println("出來吃飯了");
}

構(gòu)造函數(shù)new CountDownLatch(3)

    public CountDownLatch(int count) {
        if (count < 0) throw new IllegalArgumentException("count < 0");
        this.sync = new Sync(count);
    }

Sync代碼繼承AQS
    private static final class Sync extends AbstractQueuedSynchronizer {
//將AQS的state設(shè)置為count
        Sync(int count) {
            setState(count);
        }
}

countDownLatch.countDown()方法

    public void countDown() {
        sync.releaseShared(1);
    }

    public final boolean releaseShared(int arg) {
//判斷是否達到臨界點达舒,能否釋放鎖
        if (tryReleaseShared(arg)) {
            doReleaseShared();
            return true;
        }
        return false;
    }

//主要是利用cas獲取
        protected boolean tryReleaseShared(int releases) {
            for (;;) {
                int c = getState();
                if (c == 0)
                    return false;
                int nextc = c-1;

                if (compareAndSetState(c, nextc))
                    return nextc == 0;
            }
        }

/*
* 釋放鎖
*/

    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;
        }
    }

countDownLatch.await();

    public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }
    public final void acquireSharedInterruptibly(int arg)
            throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
//判斷state是否大于0牡直,如果其他的countdown方法已經(jīng)執(zhí)行完了這邊會返回1橄维,這個時候這邊不會進入該方法武契,也不會中斷線程钾虐,直接執(zhí)行下面的業(yè)務(wù)邏輯
        if (tryAcquireShared(arg) < 0)
            doAcquireSharedInterruptibly(arg);
    }

        protected int tryAcquireShared(int acquires) {
            return (getState() == 0) ? 1 : -1;
        }

    private void doAcquireSharedInterruptibly(int arg)
        throws InterruptedException {
//添加一個waiter梳码,設(shè)置模式為SHARED(包含初始化waiter隊列,可參考AQS文章)
        final Node node = addWaiter(Node.SHARED);
        boolean failed = true;
        try {
            for (;;) {
//找到頭結(jié)點
                final Node p = node.predecessor();
                if (p == head) {
                    int r = tryAcquireShared(arg);
//如果state為0則返回1(getState() == 0) ? 1 : -1
                    if (r >= 0) {
//當(dāng)state為0智什,則表示waiter可以執(zhí)行了
                        setHeadAndPropagate(node, r);
                        p.next = null; // help GC
                        failed = false;
                        return;
                    }
                }
//停止該線程,喚醒線程也是這邊喚醒的
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    throw new InterruptedException();
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末备埃,一起剝皮案震驚了整個濱河市篓足,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌鸭限,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,348評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件两踏,死亡現(xiàn)場離奇詭異败京,居然都是意外死亡,警方通過查閱死者的電腦和手機梦染,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評論 2 385
  • 文/潘曉璐 我一進店門赡麦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人帕识,你說我怎么就攤上這事泛粹。” “怎么了肮疗?”我有些...
    開封第一講書人閱讀 156,936評論 0 347
  • 文/不壞的土叔 我叫張陵晶姊,是天一觀的道長。 經(jīng)常有香客問我伪货,道長们衙,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,427評論 1 283
  • 正文 為了忘掉前任碱呼,我火速辦了婚禮蒙挑,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘巍举。我一直安慰自己,他們只是感情好凝垛,可當(dāng)我...
    茶點故事閱讀 65,467評論 6 385
  • 文/花漫 我一把揭開白布懊悯。 她就那樣靜靜地躺著,像睡著了一般梦皮。 火紅的嫁衣襯著肌膚如雪炭分。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,785評論 1 290
  • 那天剑肯,我揣著相機與錄音捧毛,去河邊找鬼。 笑死让网,一個胖子當(dāng)著我的面吹牛呀忧,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播溃睹,決...
    沈念sama閱讀 38,931評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼而账,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了因篇?” 一聲冷哼從身側(cè)響起泞辐,我...
    開封第一講書人閱讀 37,696評論 0 266
  • 序言:老撾萬榮一對情侶失蹤笔横,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后咐吼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吹缔,經(jīng)...
    沈念sama閱讀 44,141評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,483評論 2 327
  • 正文 我和宋清朗相戀三年锯茄,在試婚紗的時候發(fā)現(xiàn)自己被綠了厢塘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,625評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡撇吞,死狀恐怖俗冻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情牍颈,我是刑警寧澤迄薄,帶...
    沈念sama閱讀 34,291評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站煮岁,受9級特大地震影響讥蔽,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜画机,卻給世界環(huán)境...
    茶點故事閱讀 39,892評論 3 312
  • 文/蒙蒙 一冶伞、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧步氏,春花似錦响禽、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至界阁,卻和暖如春侯繁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背泡躯。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工贮竟, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人较剃。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓咕别,卻偏偏與公主長得像,于是被迫代替她去往敵國和親写穴。 傳聞我的和親對象是個殘疾皇子顷级,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,492評論 2 348

推薦閱讀更多精彩內(nèi)容