CountDownLatch使用場景

CountDownLatch 是由java併發包提供的一個同步計數器,從字面意義上去理解可以分成兩部分CountDown 和 Latch,CountDown就是計數的意思,Latch是門閂,這個同步工具就是通過保證多線程環境下,通過門閂限制主線程執行,子線程執行後計數減1,直到減爲0,門閂打開,主線程執行。

場景一:主任務等待其它子任務完成後再執行。

背景:電影院等待所有人都到齊了還開始播放電影,有一個電影院的類爲主線程,看電影的人爲子線程,假設電影院能容納5人看電影,下面的類將利用CountDownLatch實現該功能。

public class Cinema {
    public static void main(String[] args) {
        CountDownLatch countDownLatch = new CountDownLatch(5);
        ExecutorService executor = Executors.newFixedThreadPool(3);
        for(int i=0; i<5; i++){
            executor.execute(new Person(countDownLatch));
        }

        System.out.println("電影院等待人入場...");
        //阻塞當前線程,直到計數器的值爲0
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("人已到齊,開始播放電影...");
    }
}
public class Person implements Runnable{
    private CountDownLatch countDownLatch;
    public Person(CountDownLatch countDownLatch){
        this.countDownLatch = countDownLatch;
    }


    @Override
    public void run() {
        try {
            Thread.sleep((long) (Math.random() * 0));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(String.format("%s又有觀衆入場了", Thread.currentThread().getId()));
        countDownLatch.countDown();
        System.out.println(String.format("%s還有%s人未入場", Thread.currentThread().getId(), countDownLatch.getCount()));
    }
}

執行下看結果:

電影院等待人入場...
13又有觀衆入場了
11又有觀衆入場了
12又有觀衆入場了
11還有3人未入場
13還有4人未入場
12還有2人未入場
13又有觀衆入場了
11又有觀衆入場了
13還有1人未入場
人已到齊,開始播放電影...
11還有0人未入場

這個時候可以思考一下現實情況,不是任何時候電影院都是滿場才放電影的,那麼就需要設置一個時間,如果到時間了人還未到齊,就開始播放電影,這個程序怎麼寫呢。

public class Cinema {
    public static void main(String[] args) {
        CountDownLatch countDownLatch = new CountDownLatch(10);
        ExecutorService executor = Executors.newFixedThreadPool(3);
        for(int i=0; i<5; i++){
            executor.execute(new Person(countDownLatch));
        }

        System.out.println("電影院等待人入場...");
        //阻塞當前線程,直到計數器的值爲0
        try {
            countDownLatch.await(300, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("人已到齊,開始播放電影...");
    }
}

這裏用了CountDownLatch的await的另外一個重載方法,並且增加了CountDownLatch的閾值,讓人更多一些方便跑數據。看結果:

電影院等待人入場...
12又有觀衆入場了
13又有觀衆入場了
13還有8人未入場
12還有9人未入場
11又有觀衆入場了
11還有7人未入場
12又有觀衆入場了
12還有6人未入場
13又有觀衆入場了
13還有5人未入場
人已到齊,開始播放電影...

發現還有5人未到場的時候,電影就開始播放了,是不是很贊。現在大家是不是對CountDownLatch的使用得心應手了,在這裏需要提醒的是多線程環境下一定要注意異常,如果發生了異常該如何保證數據一致性,主線程是否要做回滾處理。我們在利用多線程實現性能提升的時候,必然會有線程安全的問題。

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