記錄CountDownLatch的一次簡單使用

最近這邊連續下了好幾天的雨了啊啊啊,你那邊呢?
嗯哼?這開場的感覺不對呀,好尬,哈哈哈哈~
直接進入正題吧。

什麼是CountDownLatch

這個是在JDK1.5開始就出現的,併發編程工具類。
這裏偷懶下,直接看下源碼上的類註釋吧,相信你看完就差不多大概知道這個幹啥子用的了。
在這裏插入圖片描述
在這裏,請允許我用本人的蹩腳英文稍微翻譯下:

可以允許一個或者多個線程等待,直到一組在其它線程裏的操作都完成,然後再執行。
初始化CountDownLatch時提供一個count數,主方法一直將被阻塞直到多次調用CountDownLatch對象的countDown方法使得count數減至0爲止。當所有等待的線程都被釋放了,await後的一系列調用都立即返回(執行)。CountDownLatch只能執行一次這樣的控制,如果你需要每個版本都重置下count數,可以考慮下CyclicBarrier。

怎麼用呢

   public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(3);//計數器最初:3個任務
        MyWork work1 = new MyWork(countDownLatch, "1號");
        MyWork work2 = new MyWork(countDownLatch, "2號");
        MyWork work3 = new MyWork(countDownLatch, "3號");
        //固定大小線程池並行執行(每個任務都在不同的線程池裏)
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        executorService.submit(work1);
        executorService.submit(work2);
        executorService.submit(work3);
        //等待所有的任務完成
        countDownLatch.await();
        //所有任務完成,可以幹其它的事情啦
        System.out.println("所有任務都完成啦");
    }

    static class MyWork implements Runnable {
        CountDownLatch countDownLatch;
        private String missionFlg;

        public MyWork(CountDownLatch countDownLatch, String missionFlg) {
            this.countDownLatch = countDownLatch;
            this.missionFlg = missionFlg;
        }

        @Override
        public void run() {
            try {
                //執行業務邏輯
                System.out.println(Thread.currentThread().getName() + "====> 執行任務" + missionFlg + "開始");
                Random random = new Random();
                //線程停留隨機停留,表示任務的執行
                TimeUnit.SECONDS.sleep(random.nextInt(5));
                System.out.println(Thread.currentThread().getName() + "====> 執行任務" + missionFlg + "結束");
            } catch (InterruptedException e) {
                System.out.println(Thread.currentThread().getName() + "====> 執行任務" + missionFlg + "出現異常");
            } finally {
                //異常的狀態下,也要記得發出信號,當前任務完成
                reduce();
            }
        }

        public void reduce() {
            //計數器減一
            countDownLatch.countDown();
        }
    }

執行結果:
在這裏插入圖片描述

自己使用過的場景

說一下自己一次的使用場景吧:

需求:產品給我一個表格,裏面大概500多條下載鏈接,需要我臨時寫一個工具,快速地全部下載 並且要 生成一個下載結果(原鏈接和下載到磁盤的路徑對照關係)。

實現:

  • 對任務列表進行拆分多個小的列表 list1,list2,list3 … listn;
  • 定義一個CountDownLatch對象,大小和上面的list的個數一致;
  • 啓動 20 個線程池,把拆分後的列表依次丟到線程池;
  • 每個list的任務,都需要記錄下每條記錄的執行結果,存儲到Redis 中;
  • 每個線程池每次執行完一個list 都 CountDownLatch裏的計數器減一;
  • CountDownLatch#await 後寫上生成 下載結果的 邏輯,這裏就是從Redis 中讀取執行結果列表,生成文件 。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章