Java併發基礎(五)-CountDownLatch、CyclocBarrier、Phaser的使用

1. CountDownLatch

一個同步工具,允許一個或多個線程去等待其他線程中執行的一系列操作完成。

什麼意思呢?就是說,允許這個線程阻塞,直到,其他線程的所有操作都完成之後,在繼續執行。舉個例子。

    public static void main(String[] args) throws InterruptedException {
        final CountDownLatch downLatch = new CountDownLatch(5);
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    System.err.println(i);
                    try {
                        Thread.sleep(1000);
                        downLatch.countDown();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
        downLatch.await();
        System.err.println("結束了");
    }

上面的例子 等五個線程都執行完畢之後,主線程纔會繼續執行。

用法如下:

  • CountDownLatch(5) 後面的數字代表等待幾個線程完成
  • 每當一個線程完成的時候,downLatch.countDown(),來使計數-1
  • downLatch.await() ,直到計數爲0的時候,纔會執行他下面的邏輯。

2. CyclocBarrier

也是一個同步工具,允許一系列線程等待其中每一個都到達一個公共的障礙點,然後在繼續執行。並且,等待的線程都釋放之後,可以重用

作爲山溝溝裏的娃,受夠了坐車等人的折磨。舉個例子。

    public static void main(String[] args){
        final CyclicBarrier cyclicBarrier = new CyclicBarrier(5, new Runnable() {
            @Override
            public void run() {
                System.err.println("到齊了。可以開車了");
            }
        });
        for (int i = 0; i < 5; i++) {
            final int finalI = i;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.err.println("買票了"+ finalI);
                    try {
                        cyclicBarrier.await();
                        System.err.println("起飛了"+ finalI);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }

輸出結果:
這裏寫圖片描述

用法:

  • CyclicBarrier(int parties, Runnable barrierAction) 構造函數中,參數一個是調用await的線程數,一個是到達障礙點之後的處理。
  • cyclicBarrier.await() 表示我要等其他也到達,纔要繼續執行

3. Phaser

一個可重用的同步工具,可以實現提CyclicBarrier和CountDownLatch的功能,但是還有其他高級的功能。

3.1 實現CountDownLatch的功能

  • CountDownLatch#countDown 由Phaser#arrive 代替
  • CountDownLatch#await 由Phaser#awaitAdvance 代替

舉個例子:

        final Phaser phaser = new Phaser(5);

        for (int i = 0; i < 5; i++) {
            final int finalI = i;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.err.println(finalI);
                    phaser.arrive();
                }
            }).start();
        }
        phaser.awaitAdvance(phaser.getPhase());
        System.err.println("結束了");

3.2 實現CyclocBarrier的功能

雖然說能實現,但是還是比較弱。

  • CyclicBarrier#await 由Phaser#arriveAndAwaitAdvance代替。
        final Phaser phaser = new Phaser(5);
        for (int i = 0; i < 5; i++) {
            final int finalI = i;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.err.println("買票了"+ finalI);
                    phaser.arriveAndAwaitAdvance();
                    System.err.println("起飛了"+ finalI);
                }
            }).start();
        }

3.3 高級功能

  • 支持register和bulkRegister方法來調整任務數,arriveAndDeregister方法支持在任務到達的時候減少任務數
  • arriveAndAwaitAdvance 表示任務到達並且等待其他任務到達
  • 支持終止,如果onAdvance返回true,就會終止,如果註冊任務數爲0,也會終止。forceTermination方法會強制終止。
  • 從它的構造函數來看,Phaser支持分層,Phaser(Phaser parent, int parties)。可以通過這些來構造出一個層次的Phaser

這些功能就不舉例子了。有興趣的同學可以去看下文檔。

參考資料

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章