漫畫:Java併發閉鎖CountDownLatch

我是程式設計師七貓發表於2019-02-26

(之前掘金的“程式設計師七貓”賬號找不到了,只好重新開了個,會把前2篇文章都搬家到這裡到)


本次漫畫改編自鴻洋的《Java 併發專題 :閉鎖 CountDownLatch 之一家人一起吃個飯》 https://blog.csdn.net/lmj623565791/article/details/26626391

謝謝鴻洋大神的支援!

某天,小貓咪一家決定要去飯館吃飯,到了快下班的時候,family·f3群裡開始聊起天來

family·f3

以下是來自這位可憐的貓咪爸爸的吐槽

貓咪爸爸到吐槽

下班到了(歡呼!),大家都開始出發去飯店了

漫畫:Java併發閉鎖CountDownLatch

public class Test1
{
    /**
     * 模擬爸爸去飯店
     */
    public static void fatherToRes()
    {
        System.out.println("爸爸步行去飯店需要3小時。");
    }
    /**
     * 模擬媽媽去飯店
     */
    public static void motherToRes()
    {
        System.out.println("媽媽擠公交去飯店需要2小時。");
    }
    /**
     * 模擬我去飯店
     */
    public static void meToRes()
    {
        System.out.println("我乘地鐵去飯店需要1小時。");
    }
    /**
     * 模擬一家人到齊了
     */
    public static void togetherToEat()
    {
        System.out.println("一家人到齊了,開始吃飯");
    }
    public static void main(String[] args)
    {
        fatherToRes();
        motherToRes();
        meToRes();
        togetherToEat();
    }
}
複製程式碼

輸出結果

爸爸步行去飯店需要3小時。
媽媽擠公交去飯店需要2小時。
我乘地鐵去飯店需要1小時。
一家人到齊了,開始吃飯
複製程式碼

!停停停 !是不是哪裡不對了,為什麼是貓咪爸爸走完3小時,媽媽再去坐公交車2小時,然後才等到小貓咪乘地鐵1小時,這整整花了6小時,那還吃什麼飯,直接買份夜宵算了!

貓咪爸爸、媽媽、小貓咪都是各自按下班時間出發的,屬於併發的,所以我們換個場景

漫畫:Java併發閉鎖CountDownLatch

開啟爸爸走路、媽媽坐公交、小貓咪坐地鐵三個執行緒,如下

public static void main(String[] args)
    {
        new Thread()
        {
            public void run()
            {
                fatherToRes();
            };
        }.start();
        new Thread()
        {
            public void run()
            {
                motherToRes();
            };
        }.start();
        new Thread()
        {
            public void run()
            {
                meToRes();
            };
        }.start();
        togetherToEat();
    }
複製程式碼

輸出結果

一家人到齊了,開始吃飯
我乘地鐵去飯店需要1小時。
媽媽擠公交去飯店需要2小時。
爸爸步行去飯店需要3小時。
複製程式碼

喵?喵?喵?!

開啟了執行緒併發了,但是貌似也不對啊,一家三都還沒到飯館,怎麼能先吃起飯來?

於是再換一個方法

private static volatile int i = 3;
    public static void main(String[] args)
    {
        new Thread()
        {
            public void run()
            {
                fatherToRes();
                i--;
            };
        }.start();
        new Thread()
        {
            public void run()
            {
                motherToRes();
                i--;
            };
        }.start();
        new Thread()
        {
            public void run()
            {
                meToRes();
                i--;
            };
        }.start();
        while (i != 0);
        togetherToEat();
    }
複製程式碼

關鍵修飾符volatile

volatile作用:當多個執行緒操作同一個變數時,用於保證變數修改對於其他執行緒的可見性。但是volatile不能保證原子性,而i--不是原子操作。所以建議正常使用同步塊或者AtomicLong.decrementAndGet()實現--。

漫畫:Java併發閉鎖CountDownLatch

馬上來~

private static CountDownLatch latch = new CountDownLatch(3);
    public static void main(String[] args) throws InterruptedException
    {
        new Thread()
        {
            public void run()
            {
                fatherToRes();
                latch.countDown();
            };
        }.start();
        new Thread()
        {
            public void run()
            {
                motherToRes();
                latch.countDown();
            };
        }.start();
        new Thread()
        {
            public void run()
            {
                meToRes();
                latch.countDown();
            };
        }.start();
        latch.await();
        togetherToEat();
    }
複製程式碼

輸出結果

我乘地鐵去飯店需要1小時。
媽媽擠公交去飯店需要2小時。
爸爸步行去飯店需要3小時。
一家人到齊了,開始吃飯
複製程式碼

CountDowmLatch是一種靈活的閉鎖實現,包含一個計數器,該計算器初始化為一個正數,表示需要等待事件的數量。countDown方法遞減計數器,表示有一個事件發生,而await方法等待計數器到達0,表示所有需要等待的事情都已經完成,那麼就可以繼續執行當前執行緒了。

CountDownLatch的使用場景

1、例如上例中所有人都到達飯店然後吃飯

2、某個操作需要的資源初始化完畢

3、某個服務依賴的執行緒全部開啟等等...

漫畫:Java併發閉鎖CountDownLatch

上烤魚嘍~

烤魚圖源來自網路侵權則刪

依然感謝支援我的小夥伴們以及網友們~

您的關注與支援是我最大的動力~

本人公眾號:程式設計師七貓

歡迎關注點贊以及提建議

漫畫:Java併發閉鎖CountDownLatch

相關文章