自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

CyclicBarrier:人齊了,老司機(jī)就發(fā)車了!

開發(fā) 后端
CyclicBarrier 翻譯為中文是循環(huán)(Cyclic)柵欄(Barrier)的意思,它的大概含義是實(shí)現(xiàn)一個(gè)可循環(huán)利用的屏障。

[[392061]]

上一篇咱講了 CountDownLatch 可以解決多個(gè)線程同步的問題,相比于 join 來說它的應(yīng)用范圍更廣,不僅可以應(yīng)用在線程上,還可以應(yīng)用在線程池上。然而 CountDownLatch 卻是一次性的計(jì)數(shù)器,以王者農(nóng)藥來說,咱們不可能一場(chǎng)團(tuán)戰(zhàn)就決定比賽的輸贏,所以在某些場(chǎng)景下,咱們是需要重復(fù)使用某個(gè)等待功能的,這就是我們今天要介紹的另一個(gè)主角——CyclicBarrier。

CyclicBarrier

CyclicBarrier 翻譯為中文是循環(huán)(Cyclic)柵欄(Barrier)的意思,它的大概含義是實(shí)現(xiàn)一個(gè)可循環(huán)利用的屏障。

CyclicBarrier 作用是讓一組線程相互等待,當(dāng)達(dá)到一個(gè)共同點(diǎn)時(shí),所有之前等待的線程再繼續(xù)執(zhí)行,且 CyclicBarrier 功能可重復(fù)使用。 å›¾ç‰‡

舉個(gè)栗子

比如磊哥要坐班車回老家,因?yàn)橹型静辉试S上、下乘客,所以營(yíng)運(yùn)的公司為了收益最大化,就會(huì)等人滿之后再發(fā)車。像這種等人坐滿就發(fā)一班車的場(chǎng)景,就是 CyclicBarrier 所擅長(zhǎng)的,因?yàn)樗梢灾貜?fù)使用(不像 CountDownLatch 那樣只能用一次)。

[[392064]]

CyclicBarrier VS CountDownLatch

CountDownLatch:一個(gè)或者多個(gè)線程,等待另外 N 個(gè)線程完成某個(gè)事情之后才能執(zhí)行。

CountDownLatch 就像玩王者農(nóng)藥開局的加載一樣,所有人要等待其他人都加載 100% 之后才能開始游戲。

CyclicBrrier:N 個(gè)線程相互等待,直到有足夠數(shù)量的線程都到達(dá)屏障點(diǎn)之后,之前等待的線程就可以繼續(xù)執(zhí)行了。

CyclicBrrier 就像老司機(jī)開車一樣,如果車上還有空余的座位,那么所有人都得等著,直到座位被坐滿之后,老司機(jī)才會(huì)發(fā)車。

 å›¾ç‰‡

CyclicBarrier使用

  1. import java.util.Date
  2. import java.util.Random; 
  3. import java.util.concurrent.*; 
  4.  
  5. public class CyclicBarrierExample { 
  6.     public static void main(String[] args) { 
  7.         // 創(chuàng)建 CyclicBarrier 
  8.         final CyclicBarrier cyclicBarrier = new CyclicBarrier(2, new Runnable() { 
  9.             @Override 
  10.             public void run() { 
  11.                 System.out.println("人滿了,準(zhǔn)備發(fā)車:" + new Date()); 
  12.             } 
  13.         }); 
  14.          
  15.         // 線程調(diào)用的任務(wù) 
  16.         Runnable runnable = new Runnable() { 
  17.             @Override 
  18.             public void run() { 
  19.                 // 生成隨機(jī)數(shù) 1-3 
  20.                 int randomNumber = new Random().nextInt(3) + 1; 
  21.                 // 進(jìn)入任務(wù) 
  22.                 System.out.println(String.format("我是:%s 再走:%d 秒就到車站了,現(xiàn)在時(shí)間:%s"
  23.                         Thread.currentThread().getName(), randomNumber, new Date())); 
  24.                 try { 
  25.                     // 模擬執(zhí)行 
  26.                     TimeUnit.SECONDS.sleep(randomNumber); 
  27.                     // 調(diào)用 CyclicBarrier 
  28.                     cyclicBarrier.await(); 
  29.                     // 任務(wù)執(zhí)行 
  30.                     System.out.println(String.format("線程:%s 上車,時(shí)間:%s"
  31.                             Thread.currentThread().getName(), new Date())); 
  32.                 } catch (InterruptedException e) { 
  33.                     e.printStackTrace(); 
  34.                 } catch (BrokenBarrierException e) { 
  35.                     e.printStackTrace(); 
  36.                 } 
  37.             } 
  38.         }; 
  39.  
  40.         // 創(chuàng)建線程池 
  41.         ExecutorService threadPool = Executors.newFixedThreadPool(10); 
  42.         // 執(zhí)行任務(wù) 1 
  43.         threadPool.submit(runnable); 
  44.         // 執(zhí)行任務(wù) 2 
  45.         threadPool.submit(runnable); 
  46.         // 執(zhí)行任務(wù) 3 
  47.         threadPool.submit(runnable); 
  48.         // 執(zhí)行任務(wù) 4 
  49.         threadPool.submit(runnable); 
  50.  
  51.         // 等待所有任務(wù)執(zhí)行完終止線程池 
  52.         threadPool.shutdown(); 
  53.     } 

以上代碼執(zhí)行結(jié)果如下:

從上述結(jié)果可以看出:當(dāng) CyclicBarrier 的計(jì)數(shù)器設(shè)置為 2 時(shí),線程 2 和 線程 3 都到屏障點(diǎn)之后,老司機(jī)才會(huì)發(fā)第一波車,再 2s 之后,線程 1 和線程 4 也同時(shí)進(jìn)入了屏障點(diǎn),這時(shí)候老司機(jī)又可以再發(fā)一波車了。

實(shí)現(xiàn)原理

我們先來看下 CyclicBarrier 的類圖:

由上圖可知 CyclicBarrier 是基于獨(dú)占鎖 ReentrantLock 實(shí)現(xiàn)的,其底層也是基于 AQS 的。

在 CyclicBarrier 類的內(nèi)部有一個(gè)計(jì)數(shù)器 count,當(dāng) count 不為 0 時(shí),每個(gè)線程在到達(dá)屏障點(diǎn)會(huì)先調(diào)用 await 方法將自己阻塞,此時(shí)計(jì)數(shù)器會(huì)減 1,直到計(jì)數(shù)器減為 0 的時(shí)候,所有因調(diào)用 await 方法而被阻塞的線程就會(huì)被喚醒繼續(xù)執(zhí)行。當(dāng) count 計(jì)數(shù)器變成 0 之后,就會(huì)進(jìn)入下一輪阻塞,此時(shí) parties(parties 是在 new CyclicBarrier(parties) 時(shí)設(shè)置的值)會(huì)將它的值賦值給 count 從而實(shí)現(xiàn)復(fù)用。

常用方法

CyclicBarrier(parties):初始化相互等待的線程數(shù)量的構(gòu)造方法。

CyclicBarrier(parties,Runnable barrierAction):初始化相互等待的線程數(shù)量以及屏障線程的構(gòu)造方法,當(dāng) CyclicBarrier 的計(jì)數(shù)器變?yōu)?0 時(shí),會(huì)執(zhí)行 barrierAction 構(gòu)造方法。

getParties():獲取 CyclicBarrier 打開屏障的線程數(shù)量,也稱為方數(shù)。

getNumberWaiting():獲取正在CyclicBarrier上等待的線程數(shù)量。

await():在 CyclicBarrier 上進(jìn)行阻塞等待,直到發(fā)生以下情形之一:在 CyclicBarrier 上等待的線程數(shù)量達(dá)到 parties,則所有線程被釋放,繼續(xù)執(zhí)行;

  • 當(dāng)前線程被中斷,則拋出 InterruptedException 異常,并停止等待,繼續(xù)執(zhí)行;
  • 其他等待的線程被中斷,則當(dāng)前線程拋出 BrokenBarrierException 異常,并停止等待,繼續(xù)執(zhí)行;
  • 其他等待的線程超時(shí),則當(dāng)前線程拋出 BrokenBarrierException 異常,并停止等待,繼續(xù)執(zhí)行;
  • 其他線程調(diào)用 CyclicBarrier.reset() 方法,則當(dāng)前線程拋出 BrokenBarrierException 異常,并停止等待,繼續(xù)執(zhí)行。

await(timeout,TimeUnit):在CyclicBarrier上進(jìn)行限時(shí)的阻塞等待,直到發(fā)生以下情形之一:

  • 在 CyclicBarrier 上等待的線程數(shù)量達(dá)到 parties,則所有線程被釋放,繼續(xù)執(zhí)行;
  • 當(dāng)前線程被中斷,則拋出 InterruptedException 異常,并停止等待,繼續(xù)執(zhí)行;
  • 當(dāng)前線程等待超時(shí),則拋出 TimeoutException 異常,并停止等待,繼續(xù)執(zhí)行;
  • 其他等待的線程被中斷,則當(dāng)前線程拋出 BrokenBarrierException 異常,并停止等待,繼續(xù)執(zhí)行;
  • 其他等待的線程超時(shí),則當(dāng)前線程拋出 BrokenBarrierException 異常,并停止等待,繼續(xù)執(zhí)行;
  • 其他線程調(diào)用 CyclicBarrier.reset() 方法,則當(dāng)前線程拋出 BrokenBarrierException 異常,并停止等待,繼續(xù)執(zhí)行。

isBroken():獲取是否破損標(biāo)志位 broken 的值,此值有以下幾種情況:

  • CyclicBarrier 初始化時(shí),broken=false,表示屏障未破損;
  • 如果正在等待的線程被中斷,則 broken=true,表示屏障破損;
  • 如果正在等待的線程超時(shí),則 broken=true,表示屏障破損;
  • 如果有線程調(diào)用 CyclicBarrier.reset() 方法,則 broken=false,表示屏障回到未破損狀態(tài)。

reset():使得CyclicBarrier回歸初始狀態(tài),直觀來看它做了兩件事:

  • 如果有正在等待的線程,則會(huì)拋出 BrokenBarrierException 異常,且這些線程停止等待,繼續(xù)執(zhí)行。
  • 將是否破損標(biāo)志位 broken 置為 false。

總結(jié)

CyclicBrrier 是通過獨(dú)占鎖 ReentrantLock 實(shí)現(xiàn)計(jì)數(shù)器的原子性更新的,CyclicBrrier 最常用的是 await() 方法,使用此方法會(huì)將計(jì)數(shù)器 -1,并判斷當(dāng)前的計(jì)數(shù)器是否為 0,如果不為 0 就會(huì)阻塞等待,并計(jì)時(shí)器為 0 之后,才能繼續(xù)執(zhí)行剩余任務(wù)。CyclicBrrier 相比于 CountDownLatch 來說,它的優(yōu)勢(shì)在于可以重復(fù)使用。

參考 & 鳴謝

  • blog.csdn.net/qq_39241239/article/details/87030142
  • blog.csdn.net/zzg1229059735/article/details/61191679
  • www.cnblogs.com/yaochunhui/p/13494689.html

 

責(zé)任編輯:姜華 來源: Java中文社群
相關(guān)推薦

2016-10-10 08:38:40

Windows 10備份格式化

2022-01-11 16:54:16

異步編程方式

2018-12-19 10:52:35

嵌入式CPU微處理器

2017-07-17 17:13:58

老司機(jī)

2018-01-15 10:51:42

2018-06-01 16:37:05

果然是老司機(jī),效率實(shí)在

2016-11-07 12:30:59

大數(shù)據(jù)互聯(lián)網(wǎng)

2019-12-17 09:29:02

數(shù)據(jù)庫架構(gòu)分庫分表

2019-08-12 10:27:34

前端程序員網(wǎng)絡(luò)

2017-09-20 09:06:20

程序員網(wǎng)站后端服務(wù)

2019-04-28 11:59:24

Wi-Fi 6Wi-Fi網(wǎng)絡(luò)

2018-03-28 12:33:21

滴滴高德地圖平臺(tái)

2019-03-25 07:14:57

程序員工程師職業(yè)

2010-03-04 17:19:17

Android核心系統(tǒng)

2021-05-07 06:15:32

編程開發(fā)端口掃描

2020-11-09 14:15:23

代碼菜鳥老司機(jī)

2017-05-24 10:58:28

linux系統(tǒng)技巧

2023-09-15 06:59:00

AMD 32處理器撕裂者

2024-06-17 07:30:00

2021-06-16 09:55:40

程序員開源編程語言
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)