JUC併發系列(八):併發程式設計常用輔助類CountDownLatch與CyclicBarrier(手敲程式碼示例)

一顆剽悍的種子發表於2020-09-30

跑起一個程式,並不難;難的是,能讓程式跑多遠!—— 一顆剽悍的種子

在這裡插入圖片描述
JUC併發系列

JUC併發系列(一):什麼?聽說你搞混了併發和並行
JUC併發系列(二):詳解Condition實現精準通知喚醒
JUC併發系列(三):面試問併發,一問鎖就懵(怒肝一篇透徹理解鎖,面試不慌)
JUC併發系列(四):【面試常問】多種方法解決ArrayList非執行緒安全,詳解CopyOnWriteArrayList
JUC併發系列(五):CopyOnWriteArraySet解決HashSet非執行緒安全
JUC併發系列(六):ConcurrentHashMap解決HashMap非執行緒安全
JUC併發系列(七):觸及Callable

走進JUC併發程式設計中必經的三個常用輔助類,CountDownLatch、CyclicBarrier與Semaphore。CountDownLatch和CyclicBarrier可以拿來一起講,雖然不同,但彼此卻很相近。

一、什麼是 CountDownLatch?

CountDownLatch在jdk1.5被引入,是在java.util.cucurrent包下,允許一個或多個執行緒等待直到在其他執行緒中指向完畢的同步輔助。

可以簡單的理解作用:countDownLatch是等待其他執行緒執行完畢後再執行本身類的執行緒。

1.關鍵程式碼及原理

通過一個倒計數器實現,計數器初始值是執行緒數量。當一個執行緒執行完,計數器值-1,當計數器值為0表示所有執行緒執行完,最後等待的執行緒才可以恢復執行。

CountDownLatch裡的count引數是計數值,計數值不能大於所執行的執行緒數,否則滿足不了條件不再執行。

CountDownLatch(int count);

countDown 數量 -1

countDownLatch.countDown();	//數量-1

等待倒計數器為 0,再往下執行

countDownLatch.await();//等待倒計數器為0

2.手敲程式碼示例

public class Demo{
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Integer x = 5;
        CountDownLatch countDownLatch = new CountDownLatch(x);
        for (int i = 0; i < x; i++) {
            new Thread(()->{
                System.out.println(Thread.currentThread().getName());
                countDownLatch.countDown();
            }).start();
        }
        countDownLatch.await();
        System.out.println("執行完畢");
    }
}

3.執行結果

在這裡插入圖片描述

二、什麼是 CyclicBarrier?

其實你理解了CountDownLatch也就理解CyclicBarrier,上面的CountDownLatch是倒計數器,計數器的值是每次遞減,而CyclicBarrier是計數器,是每次遞增。前者可以說是在做減法,而後者是在做加法。這也是為什麼我會把這兩個關鍵字放在一起講的原因,有比較的學習,才會更加清晰。

2.手敲程式碼示例

public class Demo{
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Integer x = 5;
        CyclicBarrier cyclicBarrier = new CyclicBarrier(x,()->{
           System.out.println("執行完畢");
        });

        for (Integer i = 0; i <= x; i++) {
            new Thread(()->{
                System.out.println(Thread.currentThread().getName());
                try {
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

3.執行結果

在這裡插入圖片描述

三、最後

最後的最後,為了更好的閱讀體驗,我把想說的話都放在了下面,嘿嘿。

我是一顆剽悍的種子 把我會的,認真的分享 是我寫部落格一直不變的信條。
如果你能看到這篇博文,說明我們們還是很有緣的;希望能帶給你一些許幫助,創作的不易,
把我文章的知識帶走,你的三連留下,點贊,評論,關注,是我最大的動力。

相關文章