日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線(xiàn)溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
CyclicBarrier:人齊了,老司機(jī)就發(fā)車(chē)了!

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

創(chuàng)新互聯(lián)主要從事網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)洛浦,十年網(wǎng)站建設(shè)經(jīng)驗(yàn),價(jià)格優(yōu)惠、服務(wù)專(zhuān)業(yè),歡迎來(lái)電咨詢(xún)建站服務(wù):13518219792

CyclicBarrier

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

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

舉個(gè)栗子

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

CyclicBarrier VS CountDownLatch

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

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

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

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

CyclicBarrier使用

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

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

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

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

我們先來(lái)看下 CyclicBarrier 的類(lèi)圖:

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

在 CyclicBarrier 類(lèi)的內(nèi)部有一個(gè)計(jì)數(shù)器 count,當(dāng) count 不為 0 時(shí),每個(gè)線(xiàn)程在到達(dá)屏障點(diǎn)會(huì)先調(diào)用 await 方法將自己阻塞,此時(shí)計(jì)數(shù)器會(huì)減 1,直到計(jì)數(shù)器減為 0 的時(shí)候,所有因調(diào)用 await 方法而被阻塞的線(xiàn)程就會(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):初始化相互等待的線(xiàn)程數(shù)量的構(gòu)造方法。

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

getParties():獲取 CyclicBarrier 打開(kāi)屏障的線(xiàn)程數(shù)量,也稱(chēng)為方數(shù)。

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

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

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

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

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

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

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

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

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

總結(jié)

CyclicBrrier 是通過(guò)獨(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 來(lái)說(shuō),它的優(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

分享標(biāo)題:CyclicBarrier:人齊了,老司機(jī)就發(fā)車(chē)了!
當(dāng)前路徑:http://www.5511xx.com/article/cdhihdh.html