摘要:因?yàn)樵撛卺尫诺却€程后可以重用,所以稱它為循環(huán)的。若在繼續(xù)所有參與線程之前更新共享狀態(tài),此屏障操作很有用。返回要求啟動(dòng)此的參與者數(shù)目。查詢此屏障是否處于損壞狀態(tài)。將屏障重置為其初始狀態(tài)。
引言本人郵箱:
歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明網(wǎng)址 http://blog.csdn.net/tianshi_kco
github: https://github.com/kco1989/kco
代碼已經(jīng)全部托管github有需要的同學(xué)自行下載
一個(gè)同步輔助類(lèi),它允許一組線程互相等待,直到到達(dá)某個(gè)公共屏障點(diǎn) (common barrier point)。在涉及一組固定大小的線程的程序中,這些線程必須不時(shí)地互相等待,此時(shí) CyclicBarrier 很有用。因?yàn)樵?barrier 在釋放等待線程后可以重用,所以稱它為循環(huán) 的 barrier。
理論CyclicBarrier 支持一個(gè)可選的 Runnable 命令,在一組線程中的最后一個(gè)線程到達(dá)之后(但在釋放所有線程之前),該命令只在每個(gè)屏障點(diǎn)運(yùn)行一次。若在繼續(xù)所有參與線程之前更新共享狀態(tài),此屏障操作 很有用。
示例用法:下面是一個(gè)在并行分解設(shè)計(jì)中使用 barrier 的例子:
class Solver {
final int N; final float[][] data; final CyclicBarrier barrier; class Worker implements Runnable { int myRow; Worker(int row) { myRow = row; } public void run() { while (!done()) { processRow(myRow); try { barrier.await(); } catch (InterruptedException ex) { return; } catch (BrokenBarrierException ex) { return; } } } } public Solver(float[][] matrix) { data = matrix; N = matrix.length; barrier = new CyclicBarrier(N, new Runnable() { public void run() { mergeRows(...); } }); for (int i = 0; i < N; ++i) new Thread(new Worker(i)).start(); waitUntilDone(); }
}
在這個(gè)例子中,每個(gè) worker 線程處理矩陣的一行,在處理完所有的行之前,該線程將一直在屏障處等待。處理完所有的行之后,將執(zhí)行所提供的 Runnable 屏障操作,并合并這些行。如果合并者確定已經(jīng)找到了一個(gè)解決方案,那么 done() 將返回 true,所有的 worker 線程都將終止。
如果屏障操作在執(zhí)行時(shí)不依賴于正掛起的線程,則線程組中的任何線程在獲得釋放時(shí)都能執(zhí)行該操作。為方便此操作,每次調(diào)用 await() 都將返回能到達(dá)屏障處的線程的索引。然后,您可以選擇哪個(gè)線程應(yīng)該執(zhí)行屏障操作,例如:
if (barrier.await() == 0) {
// log the completion of this iteration
}
對(duì)于失敗的同步嘗試,CyclicBarrier 使用了一種要么全部要么全不 (all-or-none) 的破壞模式:如果因?yàn)橹袛唷⑹』蛘叱瑫r(shí)等原因,導(dǎo)致線程過(guò)早地離開(kāi)了屏障點(diǎn),那么在該屏障點(diǎn)等待的其他所有線程也將通過(guò) BrokenBarrierException(如果它們幾乎同時(shí)被中斷,則用 InterruptedException)以反常的方式離開(kāi)。
內(nèi)存一致性效果:線程中調(diào)用 await() 之前的操作 happen-before 那些是屏障操作的一部份的操作,后者依次 happen-before 緊跟在從另一個(gè)線程中對(duì)應(yīng) await() 成功返回的操作。
CyclicBarrier(int parties) 創(chuàng)建一個(gè)新的 CyclicBarrier,它將在給定數(shù)量的參與者(線程)處于等待狀態(tài)時(shí)啟動(dòng),但它不會(huì)在啟動(dòng) barrier 時(shí)執(zhí)行預(yù)定義的操作。
CyclicBarrier(int parties, Runnable barrierAction) 創(chuàng)建一個(gè)新的 CyclicBarrier,它將在給定數(shù)量的參與者(線程)處于等待狀態(tài)時(shí)啟動(dòng),并在啟動(dòng) barrier 時(shí)執(zhí)行給定的屏障操作,該操作由最后一個(gè)進(jìn)入 barrier 的線程執(zhí)行。
await() 在所有參與者都已經(jīng)在此 barrier 上調(diào)用 await 方法之前,將一直等待。
await(long timeout, TimeUnit unit) 在所有參與者都已經(jīng)在此屏障上調(diào)用 await 方法之前將一直等待,或者超出了指定的等待時(shí)間。
getNumberWaiting() 返回當(dāng)前在屏障處等待的參與者數(shù)目。
getParties() 返回要求啟動(dòng)此 barrier 的參與者數(shù)目。
isBroken() 查詢此屏障是否處于損壞狀態(tài)。
reset() 將屏障重置為其初始狀態(tài)。
例子還是一樣,理論是比較枯燥的,咱們還是舉例來(lái)說(shuō),比較生動(dòng)一點(diǎn).一些教科書(shū)舉一些1~100000分批累加例子.咱們不舉這種比較無(wú)聊的例子.旅游,相信很多人都喜歡吧!旅游的套路一般都出發(fā)點(diǎn)集合,入住酒店,到旅游點(diǎn)1,再到旅游點(diǎn)2,再到旅游點(diǎn)3,在集合返回.每次都某一個(gè)地點(diǎn)時(shí).導(dǎo)游都會(huì)清點(diǎn)人數(shù).不要把人給弄丟.ok,開(kāi)始編碼...
首先寫(xiě)一個(gè)旅游類(lèi) TourismRunnable,run方法很簡(jiǎn)單就調(diào)用tourism()旅游的行程,然后在tourism,再調(diào)用旅游點(diǎn)路程,看代碼..
public class TourismRunnable implements Runnable{ CyclicBarrier cyclicBarrier; Random random; public TourismRunnable(CyclicBarrier cyclicBarrier) { this.cyclicBarrier = cyclicBarrier; this.random = new Random(); } @Override public void run() { tourism(); } /** * 旅游過(guò)程 */ private void tourism() { goToStartingPoint(); goToHotel(); goToTourismPoint1(); goToTourismPoint2(); goToTourismPoint3(); goToEndPoint(); } /** * 裝備返程 */ private void goToEndPoint() { goToPoint("飛機(jī)場(chǎng),準(zhǔn)備登機(jī)回家"); } /** * 到達(dá)旅游點(diǎn)3 */ private void goToTourismPoint3() { goToPoint("旅游點(diǎn)3"); } /** * 到達(dá)旅游點(diǎn)2 */ private void goToTourismPoint2() { goToPoint("旅游點(diǎn)2"); } /** * 到達(dá)旅游點(diǎn)1 */ private void goToTourismPoint1() { goToPoint("旅游點(diǎn)1"); } /** * 入住酒店 */ private void goToHotel() { goToPoint("酒店"); } /** * 出發(fā)點(diǎn)集合 */ private void goToStartingPoint() { goToPoint("出發(fā)點(diǎn)"); } private int getRandomTime(){ int time = this.random.nextInt(400) + 100; try { Thread.sleep(time); } catch (InterruptedException e) { e.printStackTrace(); } return time; } private void goToPoint(String point){ try { String name = Thread.currentThread().getName(); System.out.println(name + " 花了 " + getRandomTime() + " 時(shí)間才到了" + point); cyclicBarrier.await(); } catch (Exception e) { e.printStackTrace(); } } }
在每個(gè)旅游點(diǎn),每個(gè)人旅游所花的時(shí)間是隨機(jī)的,有些人玩的比較久一點(diǎn),有些則走馬觀花,拍拍照就完事了
再寫(xiě)一個(gè)測(cè)試類(lèi),讓一群小朋友去旅游吧
public class TestMain { public static void main(String[] args) { String name = "明剛紅麗黑白"; CyclicBarrier cyclicBarrier = new CyclicBarrier(name.length(), new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName() + " 清點(diǎn)人數(shù),1,2,3...,ok,人到齊了,準(zhǔn)備出發(fā)..... go go go...."); } }); ListtourismThread = new ArrayList<>(); for (char ch : name.toCharArray()){ tourismThread.add(new Thread(new TourismRunnable(cyclicBarrier), "小" + ch)); } for (Thread thread : tourismThread){ thread.start(); } } }
運(yùn)行結(jié)果:
小剛 花了 131 時(shí)間才到了出發(fā)點(diǎn) 小黑 花了 237 時(shí)間才到了出發(fā)點(diǎn) 小麗 花了 250 時(shí)間才到了出發(fā)點(diǎn) 小紅 花了 335 時(shí)間才到了出發(fā)點(diǎn) 小明 花了 379 時(shí)間才到了出發(fā)點(diǎn) 小白 花了 398 時(shí)間才到了出發(fā)點(diǎn) 小白 清點(diǎn)人數(shù),1,2,3...,ok,人到齊了,準(zhǔn)備出發(fā)..... go go go.... 小紅 花了 128 時(shí)間才到了酒店 小剛 花了 156 時(shí)間才到了酒店 小黑 花了 240 時(shí)間才到了酒店 小白 花了 280 時(shí)間才到了酒店 小明 花了 492 時(shí)間才到了酒店 小麗 花了 499 時(shí)間才到了酒店 小麗 清點(diǎn)人數(shù),1,2,3...,ok,人到齊了,準(zhǔn)備出發(fā)..... go go go.... 小麗 花了 188 時(shí)間才到了旅游點(diǎn)1 小剛 花了 315 時(shí)間才到了旅游點(diǎn)1 小明 花了 374 時(shí)間才到了旅游點(diǎn)1 小白 花了 395 時(shí)間才到了旅游點(diǎn)1 小黑 花了 428 時(shí)間才到了旅游點(diǎn)1 小紅 花了 496 時(shí)間才到了旅游點(diǎn)1 小紅 清點(diǎn)人數(shù),1,2,3...,ok,人到齊了,準(zhǔn)備出發(fā)..... go go go.... 小明 花了 206 時(shí)間才到了旅游點(diǎn)2 小剛 花了 223 時(shí)間才到了旅游點(diǎn)2 小紅 花了 302 時(shí)間才到了旅游點(diǎn)2 小白 花了 308 時(shí)間才到了旅游點(diǎn)2 小黑 花了 317 時(shí)間才到了旅游點(diǎn)2 小麗 花了 400 時(shí)間才到了旅游點(diǎn)2 小麗 清點(diǎn)人數(shù),1,2,3...,ok,人到齊了,準(zhǔn)備出發(fā)..... go go go.... 小白 花了 100 時(shí)間才到了旅游點(diǎn)3 小麗 花了 132 時(shí)間才到了旅游點(diǎn)3 小紅 花了 157 時(shí)間才到了旅游點(diǎn)3 小黑 花了 165 時(shí)間才到了旅游點(diǎn)3 小剛 花了 375 時(shí)間才到了旅游點(diǎn)3 小明 花了 416 時(shí)間才到了旅游點(diǎn)3 小明 清點(diǎn)人數(shù),1,2,3...,ok,人到齊了,準(zhǔn)備出發(fā)..... go go go.... 小剛 花了 100 時(shí)間才到了飛機(jī)場(chǎng),準(zhǔn)備登機(jī)回家 小黑 花了 137 時(shí)間才到了飛機(jī)場(chǎng),準(zhǔn)備登機(jī)回家 小紅 花了 232 時(shí)間才到了飛機(jī)場(chǎng),準(zhǔn)備登機(jī)回家 小明 花了 260 時(shí)間才到了飛機(jī)場(chǎng),準(zhǔn)備登機(jī)回家 小麗 花了 264 時(shí)間才到了飛機(jī)場(chǎng),準(zhǔn)備登機(jī)回家 小白 花了 394 時(shí)間才到了飛機(jī)場(chǎng),準(zhǔn)備登機(jī)回家 小白 清點(diǎn)人數(shù),1,2,3...,ok,人到齊了,準(zhǔn)備出發(fā)..... go go go....
ok, 運(yùn)行結(jié)果一目了然,中途沒(méi)有落下任何一個(gè)人!CyclicBarrier這個(gè)類(lèi),還是比較容易使用的
打賞如果覺(jué)得我的文章寫(xiě)的還過(guò)得去的話,有錢(qián)就捧個(gè)錢(qián)場(chǎng),沒(méi)錢(qián)給我捧個(gè)人場(chǎng)(幫我點(diǎn)贊或推薦一下)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/69921.html
摘要:本人郵箱歡迎轉(zhuǎn)載轉(zhuǎn)載請(qǐng)注明網(wǎng)址代碼已經(jīng)全部托管有需要的同學(xué)自行下載引言講完了和今天講一個(gè)跟這兩個(gè)類(lèi)有點(diǎn)類(lèi)似的移相器中引入了一種新的可重復(fù)使用的同步屏障稱為移相器擁有與和類(lèi)似的功勞但是這個(gè)類(lèi)提供了更加靈活的應(yīng)用和都是只適用于固定數(shù)量的參與者 本人郵箱: 歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明網(wǎng)址 http://blog.csdn.net/tianshi_kcogithub: https://github....
摘要:線程可以調(diào)用的方法進(jìn)入阻塞,當(dāng)計(jì)數(shù)值降到時(shí),所有之前調(diào)用阻塞的線程都會(huì)釋放。注意的初始計(jì)數(shù)值一旦降到,無(wú)法重置。 showImg(https://segmentfault.com/img/remote/1460000016012041); 本文首發(fā)于一世流云的專(zhuān)欄:https://segmentfault.com/blog... 一、CountDownLatch簡(jiǎn)介 CountDow...
摘要:當(dāng)?shù)竭_(dá)柵欄后,由于沒(méi)有滿足總數(shù)的要求,所以會(huì)一直等待,當(dāng)線程到達(dá)后,柵欄才會(huì)放行。任務(wù)其實(shí)就是當(dāng)最后一個(gè)線程到達(dá)柵欄時(shí),后續(xù)立即要執(zhí)行的任務(wù)。 showImg(https://segmentfault.com/img/remote/1460000016010958); 本文首發(fā)于一世流云專(zhuān)欄:https://segmentfault.com/blog... 一、CyclicBarri...
摘要:本人郵箱歡迎轉(zhuǎn)載轉(zhuǎn)載請(qǐng)注明網(wǎng)址代碼已經(jīng)全部托管有需要的同學(xué)自行下載引言有一個(gè)同步助手可以讓一個(gè)或一些線程等待直到另外一些線程執(zhí)行完一些操作這就是理論在初始化的時(shí)候需要一個(gè)參數(shù)調(diào)用的線程會(huì)一直等待直到其他線程調(diào)用使清空為通常所有等待中的線程會(huì) 本人郵箱: 歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明網(wǎng)址 http://blog.csdn.net/tianshi_kcogithub: https://github...
摘要:倒計(jì)時(shí)鎖,線程中調(diào)用使進(jìn)程進(jìn)入阻塞狀態(tài),當(dāng)達(dá)成指定次數(shù)后通過(guò)繼續(xù)執(zhí)行每個(gè)線程中剩余的內(nèi)容。實(shí)現(xiàn)分階段的的功能測(cè)試代碼拿客網(wǎng)站群三產(chǎn)創(chuàng)建于年月日。 同步器 為每種特定的同步問(wèn)題提供了解決方案 Semaphore Semaphore【信號(hào)標(biāo);旗語(yǔ)】,通過(guò)計(jì)數(shù)器控制對(duì)共享資源的訪問(wèn)。 測(cè)試類(lèi): package concurrent; import concurrent.th...
閱讀 1525·2023-04-25 17:41
閱讀 3045·2021-11-22 15:08
閱讀 846·2021-09-29 09:35
閱讀 1611·2021-09-27 13:35
閱讀 3327·2021-08-31 09:44
閱讀 2720·2019-08-30 13:20
閱讀 1943·2019-08-30 13:00
閱讀 2563·2019-08-26 12:12