您好,登錄后才能下訂單哦!
這篇文章主要介紹了Java中的CyclicBarrier源碼分析的相關(guān)知識,內(nèi)容詳細(xì)易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇Java中的CyclicBarrier源碼分析文章都會有所收獲,下面我們一起來看看吧。
對于CountDownLatch
,其他線程為游戲玩家,比如英雄聯(lián)盟,主線程為控制游戲開始的線程。在所有的玩家都準(zhǔn)備好之前,主線程是處于等待狀態(tài)的,也就是游戲不能開始。當(dāng)所有的玩家準(zhǔn)備好之后,下一步的動作實(shí)施者為主線程,即開始游戲。
對于CyclicBarrier,假設(shè)有一家公司要全體員工進(jìn)行團(tuán)建活動,活動內(nèi)容為翻越三個障礙物,每一個人翻越障礙物所用的時間是不一樣的。但是公司要求所有人在翻越當(dāng)前障礙物之后再開始翻越下一個障礙物,也就是所有人翻越第一個障礙物之后,才開始翻越第二個,以此類推。類比地,每一個員工都是一個“其他線程”。當(dāng)所有人都翻越的所有的障礙物之后,程序才結(jié)束。而主線程可能早就結(jié)束了,這里我們不用管主線程。
CyclicBarrier沒有顯示繼承哪個父類或者實(shí)現(xiàn)哪個父接口, 所有AQS和重入鎖不是通過繼承實(shí)現(xiàn)的,而是通過組合實(shí)現(xiàn)的。
public class CyclicBarrier {} ``` ### 類的內(nèi)部類 CyclicBarrier類存在一個內(nèi)部類Generation,每一次使用的CycBarrier可以當(dāng)成Generation的實(shí)例,其源代碼如下 ```java private static class Generation { boolean broken = false; }
說明: Generation類有一個屬性broken,用來表示當(dāng)前屏障是否被損壞。
public class CyclicBarrier { /** The lock for guarding barrier entry */ // 可重入鎖 private final ReentrantLock lock = new ReentrantLock(); /** Condition to wait on until tripped */ // 條件隊(duì)列 private final Condition trip = lock.newCondition(); /** The number of parties */ // 參與的線程數(shù)量 private final int parties; /* The command to run when tripped */ // 由最后一個進(jìn)入 barrier 的線程執(zhí)行的操作 private final Runnable barrierCommand; /** The current generation */ // 當(dāng)前代 private Generation generation = new Generation(); // 正在等待進(jìn)入屏障的線程數(shù)量 private int count; }
說明: 該屬性有一個為ReentrantLock對象,有一個為Condition對象,而Condition對象又是基于AQS的,所以,歸根到底,底層還是由AQS提供支持。
CyclicBarrier(int, Runnable)型構(gòu)造函數(shù)
public CyclicBarrier(int parties, Runnable barrierAction) { // 參與的線程數(shù)量小于等于0,拋出異常 if (parties <= 0) throw new IllegalArgumentException(); // 設(shè)置parties this.parties = parties; // 設(shè)置count this.count = parties; // 設(shè)置barrierCommand this.barrierCommand = barrierAction; }
說明: 該構(gòu)造函數(shù)可以指定關(guān)聯(lián)該CyclicBarrier的線程數(shù)量,并且可以指定在所有線程都進(jìn)入屏障后的執(zhí)行動作,該執(zhí)行動作由最后一個進(jìn)行屏障的線程執(zhí)行。
CyclicBarrier(int)型構(gòu)造函數(shù)
public CyclicBarrier(int parties) { // 調(diào)用含有兩個參數(shù)的構(gòu)造函數(shù) this(parties, null); }
說明: 該構(gòu)造函數(shù)僅僅執(zhí)行了關(guān)聯(lián)該CyclicBarrier的線程數(shù)量,沒有設(shè)置執(zhí)行動作。
此函數(shù)為CyclicBarrier類的核心函數(shù),CyclicBarrier類對外提供的await函數(shù)在底層都是調(diào)用該了doawait函數(shù),
其源代碼如下:
private int dowait(boolean timed, long nanos) throws InterruptedException, BrokenBarrierException, TimeoutException { // 保存當(dāng)前鎖 final ReentrantLock lock = this.lock; // 鎖定 lock.lock(); try { // 保存當(dāng)前代 final Generation g = generation; if (g.broken) // 屏障被破壞,拋出異常 throw new BrokenBarrierException(); if (Thread.interrupted()) { // 線程被中斷 // 損壞當(dāng)前屏障,并且喚醒所有的線程,只有擁有鎖的時候才會調(diào)用 breakBarrier(); // 拋出異常 throw new InterruptedException(); } // 減少正在等待進(jìn)入屏障的線程數(shù)量 int index = --count; if (index == 0) { // 正在等待進(jìn)入屏障的線程數(shù)量為0,所有線程都已經(jīng)進(jìn)入 // 運(yùn)行的動作標(biāo)識 boolean ranAction = false; try { // 保存運(yùn)行動作 final Runnable command = barrierCommand; if (command != null) // 動作不為空 // 運(yùn)行 command.run(); // 設(shè)置ranAction狀態(tài) ranAction = true; // 進(jìn)入下一代 nextGeneration(); return 0; } finally { if (!ranAction) // 沒有運(yùn)行的動作 // 損壞當(dāng)前屏障 breakBarrier(); } } // loop until tripped, broken, interrupted, or timed out // 無限循環(huán) for (;;) { try { if (!timed) // 沒有設(shè)置等待時間 // 等待 trip.await(); else if (nanos > 0L) // 設(shè)置了等待時間,并且等待時間大于0 // 等待指定時長 nanos = trip.awaitNanos(nanos); } catch (InterruptedException ie) { if (g == generation && ! g.broken) { // 等于當(dāng)前代并且屏障沒有被損壞 // 損壞當(dāng)前屏障 breakBarrier(); // 拋出異常 throw ie; } else { // 不等于當(dāng)前帶后者是屏障被損壞 // We're about to finish waiting even if we had not // been interrupted, so this interrupt is deemed to // "belong" to subsequent execution. // 中斷當(dāng)前線程 Thread.currentThread().interrupt(); } } if (g.broken) // 屏障被損壞,拋出異常 throw new BrokenBarrierException(); if (g != generation) // 不等于當(dāng)前代 // 返回索引 return index; if (timed && nanos <= 0L) { // 設(shè)置了等待時間,并且等待時間小于0 // 損壞屏障 breakBarrier(); // 拋出異常 throw new TimeoutException(); } } } finally { // 釋放鎖 lock.unlock(); } }
此函數(shù)在所有線程進(jìn)入屏障后會被調(diào)用,即生成下一個版本,所有線程又可以重新進(jìn)入到屏障中,
其源代碼如下:
private void nextGeneration() { // signal completion of last generation // 喚醒所有線程 trip.signalAll(); // set up next generation // 恢復(fù)正在等待進(jìn)入屏障的線程數(shù)量 count = parties; // 新生一代 generation = new Generation(); }
在此函數(shù)中會調(diào)用AQS的signalAll方法,即喚醒所有等待線程。如果所有的線程都在等待此條件,則喚醒所有線程。
其源代碼如:
public final void signalAll() { if (!isHeldExclusively()) // 不被當(dāng)前線程獨(dú)占,拋出異常 throw new IllegalMonitorStateException(); // 保存condition隊(duì)列頭節(jié)點(diǎn) Node first = firstWaiter; if (first != null) // 頭節(jié)點(diǎn)不為空 // 喚醒所有等待線程 doSignalAll(first); }
關(guān)于“Java中的CyclicBarrier源碼分析”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對“Java中的CyclicBarrier源碼分析”知識都有一定的了解,大家如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。