最近這邊連續下了好幾天的雨了啊啊啊,你那邊呢?
嗯哼?這開場的感覺不對呀,好尬,哈哈哈哈~
直接進入正題吧。
什麼是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 中讀取執行結果列表,生成文件 。