基于CyclicBarrier和CountDownLatch的使用區(qū)別說明
2018.12.12更新
在學習了CyclicBarrier之后發(fā)現(xiàn),CyclicBarrier也可以實現(xiàn)跟CountDownLatch類似的功能,只需要在它的parties中多設(shè)置一個數(shù),將主線程加入等待隊列就可以了:
public static void main(String[] args) {
ExecutorService pool = Executors.newCachedThreadPool();
int size = 3;
// 設(shè)置參數(shù)時,線程實際執(zhí)行數(shù)size+1,將main線程也加到等待隊列中
CyclicBarrier cyclicBarrier = new CyclicBarrier(size + 1);
for (int i = 0; i < size; i++) {
int index = i;
pool.submit(() -> {
try {
TimeUnit.SECONDS.sleep(index);
System.out.println("第" + index + "位運動員準備好了");
cyclicBarrier.await();
} catch (Exception e) {
e.printStackTrace();
}
});
}
try {
//主線程也加入等待
cyclicBarrier.await();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(size + "位運動員都準備好了,可以起跑!");
}
執(zhí)行結(jié)果:

以下是原內(nèi)容:
我在使用并發(fā)線程柵欄的時候發(fā)現(xiàn)了兩種,分別是CyclicBarrier 和CountDownLatch。對于兩者的對比的文章有很多,這里不再贅述。我來說下我的使用過程。
**需求:**有三位運動員,他們一起參加萬米賽跑,但是他們準備的時間不同,要等他們都準備好了再開始一起跑。
使用CyclicBarrier 實現(xiàn):
import java.util.concurrent.*;
public class RunTest {
public static void main(String[] args) {
ExecutorService pool = Executors.newCachedThreadPool();
int size = 3;
CyclicBarrier cyclicBarrier = new CyclicBarrier(size, () -> {
System.out.println(size + "位運動員都準備好了,可以起跑!");
pool.shutdownNow();
});
for (int i = 0; i < size; i++) {
int index = i;
pool.submit(() -> {
try {
TimeUnit.SECONDS.sleep(index);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("第" + index + "位運動員準備好了");
try {
cyclicBarrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
});
}
}
}
結(jié)果:

可以看到,三位運動員準備的時間分別是1s,2s,3s。系統(tǒng)等到他們都準備好了,再發(fā)出起跑的信號。在這里CyclicBarrier 做法是在自己的構(gòu)造器中new了一個runnable,等待其他線程都執(zhí)行完,再執(zhí)行此runnable中的代碼。
我們再看看CountDownLatch怎么實現(xiàn):
import java.util.concurrent.*;
public class RunTest {
public static void main(String[] args) throws InterruptedException {
ExecutorService pool = Executors.newCachedThreadPool();
CountDownLatch countDownLatch = new CountDownLatch(3);
int size = 3;
for (int i = 0; i < size; i++) {
int index = i;
pool.submit(() -> {
try {
TimeUnit.SECONDS.sleep(index);
countDownLatch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("第" + index + "位運動員準備好了");
});
}
countDownLatch.await();
System.out.println(size + "位運動員都準備好了,可以起跑!");
}
}
結(jié)果同上:

我們可以看到,countDownLatch是采取阻塞主線程的方法實現(xiàn)了線程的統(tǒng)一。他內(nèi)部有一個計數(shù)器,我們在執(zhí)行完一次線程任務的時候需要手動的減一個數(shù),在主線程中使用 **countDownLatch.await()**監(jiān)控計數(shù)器的狀態(tài),知道計數(shù)器計到0為止,再執(zhí)行主線程的代碼。
在實際的開發(fā)中,我個人比較傾向于第二種方法,因為使用起來簡單,完全滿足我的需求。
以上這篇基于CyclicBarrier和CountDownLatch的使用區(qū)別說明就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java異步編程之Callbacks與Futures模型詳解
這篇文章主要為大家詳細介紹了Java異步編程中Callbacks與Futures模型的使用,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下2023-03-03
Java Listener監(jiān)聽器使用規(guī)范詳細介紹
監(jiān)聽器是一個專門用于對其他對象身上發(fā)生的事件或狀態(tài)改變進行監(jiān)聽和相應處理的對象,當被監(jiān)視的對象發(fā)生情況時,立即采取相應的行動。監(jiān)聽器其實就是一個實現(xiàn)特定接口的普通java程序,這個程序?qū)iT用于監(jiān)聽另一個java對象的方法調(diào)用或?qū)傩愿淖?/div> 2023-01-01
Java中實現(xiàn)高清圖片壓縮的兩種方案(最新推薦)
文章首先介紹了Java中進行高清圖片壓縮的基本方法,包括使用Java標準庫ImageIO和第三方庫ApacheCommonsCompress,通過示例代碼展示了如何調(diào)整圖像質(zhì)量和使用第三方工具來壓縮圖片文件,感興趣的朋友跟隨小編一起看看吧2025-01-01
Java 在PDF中添加頁面跳轉(zhuǎn)按鈕功能(代碼演示)
這篇文章主要介紹了Java 在PDF中添加頁面跳轉(zhuǎn)按鈕功能,本文給大家提供了多種功能的按鈕,需要的朋友可以參考下2019-11-11
解決spring mvc 多數(shù)據(jù)源切換,不支持事務控制的問題
下面小編就為大家?guī)硪黄鉀Qspring mvc 多數(shù)據(jù)源切換,不支持事務控制的問題。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-09-09
SpringBoot異步線程父子線程數(shù)據(jù)傳遞的5種方式
這篇文章主要介紹了SpringBoot異步線程父子線程數(shù)據(jù)傳遞的5種方式,文中通過代碼示例給大家介紹的非常詳細,對大家的學習或工作有一定的幫助,需要的朋友可以參考下2024-08-08最新評論

