簡單地理解區分CountDownLatch與CyclicBarrier--高并發編程
本文主要討論在高并發編程中兩非常實用工具CyclicBarrier(同步屏障)和CountDownLatch(倒計時鎖),兩者都是java.util.concurrent并發包內非常有用的并發工具類,為了幫助理解會結合一些有趣的比喻,下面將對兩者進行討論。
一、CountDownLatch倒計時鎖(一個線程等待另外N個線程完成某個事情之后才能執行)
- //創建一個倒計時鎖,設置值為5
- final CountDownLatch latch = new CountDownLatch(5);
- try {
- //啟用5個線程
- for (int i = 1; i <= 5; i++) {
- new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- Thread.sleep(1000);
- } catch (Exception e) {
- e.printStackTrace();
- }
- System.out.println("子線程執行!");
- //讓latch鎖中的數值減1
- latch.countDown();
- }
- }).start();
- }
- //處于阻塞狀態直到latch中數值為零才執行后續操作
- latch.await();
- System.out.println("主線程執行");
- } catch (Exception e) {
- System.out.println("捕獲異常");
- }
- }
運行結果:
解析:倒計時鎖理解起來比較容易,這里通過結合實際場景幫助理解。場景:一張數據表中存放大量的數據,現要讀取表里的所有信息。為了提高讀取效率便通過在主線程中開啟多個子線程分工合作對數據表進行讀取。接下來要等待全部子線程讀取完畢之后,將讀取到的內容進行匯總并在主線程中進行處理。
- 首先先設置一個CountDownLatch倒計時鎖 ,并設置倒計時值為5
- 每一個子線程進行自己的工作,當工作執行完畢完畢后通過執行latch.countDown()對倒計時鎖的值進行減1操作,表示自己工作完成。
- 主線程latch.await() 后的代碼段一直屬于等待狀態,直到CountDownLatch的值為0時才繼續執行。
二、可循環使用的屏障CyclicBarrier(N個線程相互等待,任何一個線程完成之前,所有的線程都必須等待)
- //建立一個屏障并設定一個值,當有足夠的線程達到屏障時再一起釋放
- CyclicBarrier barrier = new CyclicBarrier(5, () -> {
- System.out.println("開始游戲");
- });
- ExecutorService executorPool = Executors.newCachedThreadPool();
- for (int i = 1; i <= 5; i++) {
- int num = i;
- Thread.sleep(1000);
- executorPool.execute(() -> {
- try {
- System.out.println(num + "號玩家,已準備好,等待進入游戲");
- barrier.await();
- System.out.println(num + "號玩家,已經進入游戲");
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (BrokenBarrierException e) {
- e.printStackTrace();
- }
- });
- }
- executorPool.shutdown();
運行結果:
解析:這里通過一個形象的例子來幫助理解CyclicBarrier。
- 一開始建立一個CyclicBarrier對象并設置parties的值為5(理解為開啟一個游戲房間,且需要5個玩家都準備好的條件之后才能開啟游戲,各個玩家才能進行游戲游玩)。
- 循環開啟多個線程并各自調用barrier.await(),理解為玩家分別都進入房間并做好了準備,線程當調用barrier.await()方法計數會加1,如果計數還達不到CyclicBarrier預先設置的parties值時則該線程會進入等待狀態。
- 當線程barrier.await()方法計數達到CyclicBarrier預先設置的parties值時,便開始游戲。這個時候所有的線程(玩家)便同時進入到了游戲中。
三、兩者對比
最后
CyclicBarrier(同步屏障)和CountDownLatch(倒計時鎖)都是不錯的高并發編程工具類,兩者很相似容易造成混淆,通過理解兩者各自工作方式和特點并結合業務需求合理地應用他們會有不錯的效益。