這是java高併發系列第17篇。java
本文主要內容:sql
CyclicBarrier一般稱爲循環屏障。它和CountDownLatch很類似,均可以使線程先等待而後再執行。不過CountDownLatch是使一批線程等待另外一批線程執行完後再執行;而CyclicBarrier只是使等待的線程達到必定數目後再讓它們繼續執行。故而CyclicBarrier內部也有一個計數器,計數器的初始值在建立對象時經過構造參數指定,以下所示:安全
public CyclicBarrier(int parties) { this(parties, null); }
每調用一次await()方法都將使阻塞的線程數+1,只有阻塞的線程數達到設定值時屏障纔會打開,容許阻塞的全部線程繼續執行。除此以外,CyclicBarrier還有幾點須要注意的地方:微信
public CyclicBarrier(int parties, Runnable barrierAction) { if (parties <= 0) throw new IllegalArgumentException(); this.parties = parties; this.count = parties; this.barrierCommand = barrierAction; }
一旦用戶在建立CyclicBarrier對象時設置了barrierAction參數,則在阻塞線程數達到設定值屏障打開前,會調用barrierAction的run()方法完成用戶自定義的操做。多線程
公司組織旅遊,你們都有經歷過,10我的,中午到飯點了,須要等到10我的都到了才能開飯,先到的人坐那等着,代碼以下:併發
package com.itsoku.chat15; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.TimeUnit; /** * 微信公衆號:javacode2018,獲取年薪50萬java課程 */ public class Demo1 { public static CyclicBarrier cyclicBarrier = new CyclicBarrier(10); public static class T extends Thread { int sleep; public T(String name, int sleep) { super(name); this.sleep = sleep; } @Override public void run() { try { //模擬休眠 TimeUnit.SECONDS.sleep(sleep); long starTime = System.currentTimeMillis(); //調用await()的時候,當前線程將會被阻塞,須要等待其餘員工都到達await了才能繼續 cyclicBarrier.await(); long endTime = System.currentTimeMillis(); System.out.println(this.getName() + ",sleep:" + this.sleep + " 等待了" + (endTime - starTime) + "(ms),開始吃飯了!"); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } } public static void main(String[] args) throws InterruptedException { for (int i = 1; i <= 10; i++) { new T("員工" + i, i).start(); } } }
輸出:socket
員工1,sleep:1 等待了9000(ms),開始吃飯了! 員工9,sleep:9 等待了1000(ms),開始吃飯了! 員工8,sleep:8 等待了2001(ms),開始吃飯了! 員工7,sleep:7 等待了3001(ms),開始吃飯了! 員工6,sleep:6 等待了4001(ms),開始吃飯了! 員工4,sleep:4 等待了6000(ms),開始吃飯了! 員工5,sleep:5 等待了5000(ms),開始吃飯了! 員工10,sleep:10 等待了0(ms),開始吃飯了! 員工2,sleep:2 等待了7999(ms),開始吃飯了! 員工3,sleep:3 等待了7000(ms),開始吃飯了!
代碼中模擬了10個員工上桌吃飯的場景,等待全部員工都到齊了才能開發,能夠看到第10個員工最慢,前面的都在等待第10個員工,員工1等待了9秒,上面代碼中調用cyclicBarrier.await();
會讓當前線程等待。當10個員工都調用了cyclicBarrier.await();
以後,全部處於等待中的員工都會被喚醒,而後繼續運行。ide
對示例1進行改造一下,吃飯完畢以後,全部人都去車上,待全部人都到車上以後,驅車去下一景點玩。高併發
package com.itsoku.chat15; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.TimeUnit; /** * 微信公衆號:javacode2018,獲取年薪50萬java課程 */ public class Demo2 { public static CyclicBarrier cyclicBarrier = new CyclicBarrier(10); public static class T extends Thread { int sleep; public T(String name, int sleep) { super(name); this.sleep = sleep; } //等待吃飯 void eat() { try { //模擬休眠 TimeUnit.SECONDS.sleep(sleep); long starTime = System.currentTimeMillis(); //調用await()的時候,當前線程將會被阻塞,須要等待其餘員工都到達await了才能繼續 cyclicBarrier.await(); long endTime = System.currentTimeMillis(); System.out.println(this.getName() + ",sleep:" + this.sleep + " 等待了" + (endTime - starTime) + "(ms),開始吃飯了!"); //休眠sleep時間,模擬當前員工吃飯耗時 TimeUnit.SECONDS.sleep(sleep); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } //等待全部人到齊以後,開車去下一站 void drive() { try { long starTime = System.currentTimeMillis(); //調用await()的時候,當前線程將會被阻塞,須要等待其餘員工都到達await了才能繼續 cyclicBarrier.await(); long endTime = System.currentTimeMillis(); System.out.println(this.getName() + ",sleep:" + this.sleep + " 等待了" + (endTime - starTime) + "(ms),去下一景點的路上!"); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } @Override public void run() { //等待全部人到齊以後吃飯,先到的人坐那等着,什麼事情不要幹 this.eat(); //等待全部人到齊以後開車去下一景點,先到的人坐那等着,什麼事情不要幹 this.drive(); } } public static void main(String[] args) throws InterruptedException { for (int i = 1; i <= 10; i++) { new T("員工" + i, i).start(); } } }
輸出:工具
員工10,sleep:10 等待了0(ms),開始吃飯了! 員工5,sleep:5 等待了5000(ms),開始吃飯了! 員工6,sleep:6 等待了4000(ms),開始吃飯了! 員工9,sleep:9 等待了1001(ms),開始吃飯了! 員工4,sleep:4 等待了6000(ms),開始吃飯了! 員工3,sleep:3 等待了7000(ms),開始吃飯了! 員工1,sleep:1 等待了9001(ms),開始吃飯了! 員工2,sleep:2 等待了8000(ms),開始吃飯了! 員工8,sleep:8 等待了2001(ms),開始吃飯了! 員工7,sleep:7 等待了3000(ms),開始吃飯了! 員工10,sleep:10 等待了0(ms),去下一景點的路上! 員工1,sleep:1 等待了8998(ms),去下一景點的路上! 員工5,sleep:5 等待了4999(ms),去下一景點的路上! 員工4,sleep:4 等待了5999(ms),去下一景點的路上! 員工3,sleep:3 等待了6998(ms),去下一景點的路上! 員工2,sleep:2 等待了7998(ms),去下一景點的路上! 員工9,sleep:9 等待了999(ms),去下一景點的路上! 員工8,sleep:8 等待了1999(ms),去下一景點的路上! 員工7,sleep:7 等待了2999(ms),去下一景點的路上! 員工6,sleep:6 等待了3999(ms),去下一景點的路上!
坑,又是員工10最慢,要提高效率了,不能吃的太多,得減肥。
代碼中CyclicBarrier至關於使用了2次,第一次用於等待全部人到達後開飯,第二次用於等待全部人上車後驅車去下一景點。注意一些先到的員工會在其餘人到達以前,都處於等待狀態(cyclicBarrier.await();
會讓當前線程阻塞),沒法幹其餘事情,等到最後一我的到了會喚醒全部人,而後繼續。
CyclicBarrier內部至關於有個計數器(構造方法傳入的),每次調用
await();
後,計數器會減1,而且await()方法會讓當前線程阻塞,等待計數器減爲0的時候,全部在await()上等待的線程被喚醒,而後繼續向下執行,此時計數器又會被還原爲建立時的值,而後能夠繼續再次使用。
仍是示例1中的例子,員工10是最後到達的,讓全部人都久等了,那怎麼辦,得給全部人倒酒,而後開飯,代碼以下:
package com.itsoku.chat15; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.TimeUnit; /** * 微信公衆號:javacode2018,獲取年薪50萬java課程 */ public class Demo3 { public static CyclicBarrier cyclicBarrier = new CyclicBarrier(10, () -> { //模擬倒酒,花了2秒,又得讓其餘9我的等2秒 try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "說,很差意思,讓你們久等了,給你們倒酒賠罪!"); }); public static class T extends Thread { int sleep; public T(String name, int sleep) { super(name); this.sleep = sleep; } @Override public void run() { try { //模擬休眠 TimeUnit.SECONDS.sleep(sleep); long starTime = System.currentTimeMillis(); //調用await()的時候,當前線程將會被阻塞,須要等待其餘員工都到達await了才能繼續 cyclicBarrier.await(); long endTime = System.currentTimeMillis(); System.out.println(this.getName() + ",sleep:" + this.sleep + " 等待了" + (endTime - starTime) + "(ms),開始吃飯了!"); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } } public static void main(String[] args) throws InterruptedException { for (int i = 1; i <= 10; i++) { new T("員工" + i, i).start(); } } }
輸出:
員工10說,很差意思,讓你們久等了,給你們倒酒賠罪! 員工10,sleep:10 等待了2000(ms),開始吃飯了! 員工1,sleep:1 等待了11000(ms),開始吃飯了! 員工2,sleep:2 等待了10000(ms),開始吃飯了! 員工5,sleep:5 等待了7000(ms),開始吃飯了! 員工7,sleep:7 等待了5000(ms),開始吃飯了! 員工9,sleep:9 等待了3000(ms),開始吃飯了! 員工4,sleep:4 等待了8000(ms),開始吃飯了! 員工3,sleep:3 等待了9001(ms),開始吃飯了! 員工8,sleep:8 等待了4001(ms),開始吃飯了! 員工6,sleep:6 等待了6001(ms),開始吃飯了!
代碼中建立CyclicBarrier
對象時,多傳入了一個參數(內部是倒酒操做),先到的人先等待,待全部人都到齊以後,須要先給你們倒酒,而後喚醒全部等待中的人讓你們開飯。從輸出結果中咱們發現,倒酒操做是由最後一我的操做的,最後一我的倒酒完畢以後,才喚醒全部等待中的其餘員工,讓你們開飯。
員工5等待中,忽然接了個電話,有點急事,而後就拿起筷子開吃了,其餘人會怎麼樣呢?看着他吃麼?
代碼以下:
package com.itsoku.chat15; import java.sql.Time; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.TimeUnit; /** * 微信公衆號:javacode2018,獲取年薪50萬java課程 */ public class Demo4 { public static CyclicBarrier cyclicBarrier = new CyclicBarrier(10); public static class T extends Thread { int sleep; public T(String name, int sleep) { super(name); this.sleep = sleep; } @Override public void run() { long starTime = 0, endTime = 0; try { //模擬休眠 TimeUnit.SECONDS.sleep(sleep); starTime = System.currentTimeMillis(); //調用await()的時候,當前線程將會被阻塞,須要等待其餘員工都到達await了才能繼續 System.out.println(this.getName() + "到了!"); cyclicBarrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } endTime = System.currentTimeMillis(); System.out.println(this.getName() + ",sleep:" + this.sleep + " 等待了" + (endTime - starTime) + "(ms),開始吃飯了!"); } } public static void main(String[] args) throws InterruptedException { for (int i = 1; i <= 10; i++) { int sleep = 0; if (i == 10) { sleep = 10; } T t = new T("員工" + i, sleep); t.start(); if (i == 5) { //模擬員工5接了個電話,將本身等待吃飯給打斷了 TimeUnit.SECONDS.sleep(1); System.out.println(t.getName() + ",有點急事,我先開幹了!"); t.interrupt(); TimeUnit.SECONDS.sleep(2); } } } }
輸出:
員工4到了! 員工3到了! 員工5到了! 員工1到了! 員工2到了! 員工5,有點急事,我先開幹了! java.util.concurrent.BrokenBarrierException 員工1,sleep:0 等待了1001(ms),開始吃飯了! at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:250) 員工3,sleep:0 等待了1001(ms),開始吃飯了! at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362) 員工4,sleep:0 等待了1001(ms),開始吃飯了! at com.itsoku.chat15.Demo4$T.run(Demo4.java:31) 員工2,sleep:0 等待了1001(ms),開始吃飯了! 員工5,sleep:0 等待了1002(ms),開始吃飯了! java.util.concurrent.BrokenBarrierException at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:250) at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362) at com.itsoku.chat15.Demo4$T.run(Demo4.java:31) java.util.concurrent.BrokenBarrierException at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:250) at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362) at com.itsoku.chat15.Demo4$T.run(Demo4.java:31) java.util.concurrent.BrokenBarrierException at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:250) at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362) at com.itsoku.chat15.Demo4$T.run(Demo4.java:31) java.lang.InterruptedException at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.reportInterruptAfterWait(AbstractQueuedSynchronizer.java:2014) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2048) at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:234) at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362) at com.itsoku.chat15.Demo4$T.run(Demo4.java:31) java.util.concurrent.BrokenBarrierException at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:207) at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362) at com.itsoku.chat15.Demo4$T.run(Demo4.java:31) java.util.concurrent.BrokenBarrierException 員工6到了! at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:207) at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362) 員工9到了! at com.itsoku.chat15.Demo4$T.run(Demo4.java:31) 員工8到了! 員工7到了! 員工6,sleep:0 等待了0(ms),開始吃飯了! 員工7,sleep:0 等待了1(ms),開始吃飯了! java.util.concurrent.BrokenBarrierException at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:207) at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362) at com.itsoku.chat15.Demo4$T.run(Demo4.java:31) java.util.concurrent.BrokenBarrierException at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:207) at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362) at com.itsoku.chat15.Demo4$T.run(Demo4.java:31) 員工8,sleep:0 等待了1(ms),開始吃飯了! 員工9,sleep:0 等待了1(ms),開始吃飯了! Disconnected from the target VM, address: '127.0.0.1:64413', transport: 'socket' java.util.concurrent.BrokenBarrierException at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:207) at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362) at com.itsoku.chat15.Demo4$T.run(Demo4.java:31) 員工10到了! 員工10,sleep:10 等待了0(ms),開始吃飯了!
輸出的信息看着有點亂,給你們理一理,員工5遇到急事,拿起筷子就是吃,這樣好麼,固然很差,他這麼作了,後面看他這麼作了都跟着這麼作(這種場景是否是很熟悉,有一我的拿起筷子先吃起來,其餘人都跟着上了),直接不等其餘人了,拿起筷子就開吃了。CyclicBarrier遇到這種狀況就是這麼處理的。前面4個員工都在await()
處等待着,員工5也在await()
上等待着,等了1秒(TimeUnit.SECONDS.sleep(1);
),接了個電話,而後給員工5發送中斷信號後(t.interrupt();
),員工5的await()方法會觸發InterruptedException
異常,此時其餘等待中的前4個員工,看着5開吃了,本身當即也不等了,內部從await()
方法中觸發BrokenBarrierException
異常,而後也開吃了,後面的6/7/8/9/10員工來了之後發現你們都開吃了,本身也不等了,6-10員工調用await()
直接拋出了BrokenBarrierException
異常,而後繼續向下。
結論:
BrokenBarrierException
異常,而後繼續執行基於示例1,員工1只願意等的5秒,5s後若是你們還沒到期,本身要開吃了,員工1開吃了,其餘人會怎麼樣呢?
package com.itsoku.chat15; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; /** * 微信公衆號:javacode2018,獲取年薪50萬java課程 */ public class Demo5 { public static CyclicBarrier cyclicBarrier = new CyclicBarrier(10); public static class T extends Thread { int sleep; public T(String name, int sleep) { super(name); this.sleep = sleep; } @Override public void run() { long starTime = 0, endTime = 0; try { //模擬休眠 TimeUnit.SECONDS.sleep(sleep); starTime = System.currentTimeMillis(); //調用await()的時候,當前線程將會被阻塞,須要等待其餘員工都到達await了才能繼續 System.out.println(this.getName() + "到了!"); if (this.getName().equals("員工1")) { cyclicBarrier.await(5, TimeUnit.SECONDS); } else { cyclicBarrier.await(); } } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } catch (TimeoutException e) { e.printStackTrace(); } endTime = System.currentTimeMillis(); System.out.println(this.getName() + ",sleep:" + this.sleep + " 等待了" + (endTime - starTime) + "(ms),開始吃飯了!"); } } public static void main(String[] args) throws InterruptedException { for (int i = 1; i <= 10; i++) { T t = new T("員工" + i, i); t.start(); } } }
輸出:
員工1到了! 員工2到了! 員工3到了! 員工4到了! 員工5到了! 員工6到了! 員工1,sleep:1 等待了5001(ms),開始吃飯了! 員工5,sleep:5 等待了1001(ms),開始吃飯了! java.util.concurrent.TimeoutException at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:257) at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:435) at com.itsoku.chat15.Demo5$T.run(Demo5.java:32) java.util.concurrent.BrokenBarrierException at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:250) at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362) at com.itsoku.chat15.Demo5$T.run(Demo5.java:34) java.util.concurrent.BrokenBarrierException at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:207) at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362) at com.itsoku.chat15.Demo5$T.run(Demo5.java:34) 員工6,sleep:6 等待了2(ms),開始吃飯了! java.util.concurrent.BrokenBarrierException 員工2,sleep:2 等待了4002(ms),開始吃飯了! at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:250) 員工3,sleep:3 等待了3001(ms),開始吃飯了! at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362) 員工4,sleep:4 等待了2001(ms),開始吃飯了! at com.itsoku.chat15.Demo5$T.run(Demo5.java:34) java.util.concurrent.BrokenBarrierException at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:250) at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362) at com.itsoku.chat15.Demo5$T.run(Demo5.java:34) java.util.concurrent.BrokenBarrierException at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:250) at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362) at com.itsoku.chat15.Demo5$T.run(Demo5.java:34) java.util.concurrent.BrokenBarrierException 員工7到了! at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:207) 員工7,sleep:7 等待了0(ms),開始吃飯了! at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362) at com.itsoku.chat15.Demo5$T.run(Demo5.java:34) 員工8到了! 員工8,sleep:8 等待了0(ms),開始吃飯了! java.util.concurrent.BrokenBarrierException at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:207) at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362) at com.itsoku.chat15.Demo5$T.run(Demo5.java:34) 員工9到了! java.util.concurrent.BrokenBarrierException 員工9,sleep:9 等待了0(ms),開始吃飯了! at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:207) at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362) at com.itsoku.chat15.Demo5$T.run(Demo5.java:34) java.util.concurrent.BrokenBarrierException 員工10到了! at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:207) at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362) 員工10,sleep:10 等待了0(ms),開始吃飯了! at com.itsoku.chat15.Demo5$T.run(Demo5.java:34)
從輸出結果中咱們能夠看到:1等待5秒以後,開吃了,其餘等待人都開吃了,後面來的人不等待,直接開吃了。
員工1調用有參await
方法等待5秒以後,觸發了TimeoutException
異常,而後繼續向下運行,其餘的在5開吃以前已經等了一會的的幾個員工,他們看到5開吃了,本身當即不等待了,也開吃了(他們的await
拋出了BrokenBarrierException
異常);還有幾個員工在5開吃以後到達的,他們直接不等待了,直接拋出BrokenBarrierException
異常,而後也開吃了。
結論:
等待超時的方法
public int await(long timeout, TimeUnit unit) throws InterruptedException,BrokenBarrierException,TimeoutException
其餘等待中或者後面到達的線程,會在await()方法上觸發BrokenBarrierException
異常,而後繼續執行
示例5中改造一下,員工1等待5秒超時以後,開吃了,打破了規則,先前等待中的以及後面到達的都不按規則來了,都拿起筷子開吃。過了一會,導遊從新告知你們,要按規則來,而後重建了規則,你們都按規則來了。
代碼以下:
package com.itsoku.chat15; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; /** * 微信公衆號:javacode2018,獲取年薪50萬java課程 */ public class Demo6 { public static CyclicBarrier cyclicBarrier = new CyclicBarrier(10); //規則是否已重建 public static boolean guizhe = false; public static class T extends Thread { int sleep; public T(String name, int sleep) { super(name); this.sleep = sleep; } @Override public void run() { long starTime = 0, endTime = 0; try { //模擬休眠 TimeUnit.SECONDS.sleep(sleep); starTime = System.currentTimeMillis(); //調用await()的時候,當前線程將會被阻塞,須要等待其餘員工都到達await了才能繼續 System.out.println(this.getName() + "到了!"); if (!guizhe) { if (this.getName().equals("員工1")) { cyclicBarrier.await(5, TimeUnit.SECONDS); } else { cyclicBarrier.await(); } } else { cyclicBarrier.await(); } } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } catch (TimeoutException e) { e.printStackTrace(); } endTime = System.currentTimeMillis(); System.out.println(this.getName() + ",sleep:" + this.sleep + " 等待了" + (endTime - starTime) + "(ms),開始吃飯了!"); } } public static void main(String[] args) throws InterruptedException { for (int i = 1; i <= 10; i++) { T t = new T("員工" + i, i); t.start(); } //等待10秒以後,重置,重建規則 TimeUnit.SECONDS.sleep(15); cyclicBarrier.reset(); guizhe = true; System.out.println("---------------你們太皮了,請你們按規則來------------------"); //再來一次 for (int i = 1; i <= 10; i++) { T t = new T("員工" + i, i); t.start(); } } }
輸出:
員工1到了! 員工2到了! 員工3到了! 員工4到了! 員工5到了! java.util.concurrent.TimeoutException at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:257) at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:435) at com.itsoku.chat15.Demo6$T.run(Demo6.java:36) java.util.concurrent.BrokenBarrierException at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:250) at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362) at com.itsoku.chat15.Demo6$T.run(Demo6.java:38) java.util.concurrent.BrokenBarrierException at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:250) at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362) at com.itsoku.chat15.Demo6$T.run(Demo6.java:38) java.util.concurrent.BrokenBarrierException at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:250) at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362) at com.itsoku.chat15.Demo6$T.run(Demo6.java:38) java.util.concurrent.BrokenBarrierException at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:250) at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362) at com.itsoku.chat15.Demo6$T.run(Demo6.java:38) java.util.concurrent.BrokenBarrierException at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:250) at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362) at com.itsoku.chat15.Demo6$T.run(Demo6.java:38) 員工6到了! 員工1,sleep:1 等待了5002(ms),開始吃飯了! 員工6,sleep:6 等待了4(ms),開始吃飯了! 員工4,sleep:4 等待了2004(ms),開始吃飯了! 員工5,sleep:5 等待了1004(ms),開始吃飯了! 員工3,sleep:3 等待了3002(ms),開始吃飯了! 員工2,sleep:2 等待了4004(ms),開始吃飯了! 員工7到了! 員工7,sleep:7 等待了0(ms),開始吃飯了! java.util.concurrent.BrokenBarrierException at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:207) at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362) at com.itsoku.chat15.Demo6$T.run(Demo6.java:38) java.util.concurrent.BrokenBarrierException at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:207) at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362) at com.itsoku.chat15.Demo6$T.run(Demo6.java:38) 員工8到了! 員工8,sleep:8 等待了0(ms),開始吃飯了! java.util.concurrent.BrokenBarrierException 員工9到了! at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:207) 員工9,sleep:9 等待了0(ms),開始吃飯了! at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362) at com.itsoku.chat15.Demo6$T.run(Demo6.java:38) java.util.concurrent.BrokenBarrierException 員工10到了! at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:207) 員工10,sleep:10 等待了0(ms),開始吃飯了! at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:362) at com.itsoku.chat15.Demo6$T.run(Demo6.java:38) ---------------你們太皮了,請你們按規則來------------------ 員工1到了! 員工2到了! 員工3到了! 員工4到了! 員工5到了! 員工6到了! 員工7到了! 員工8到了! 員工9到了! 員工10到了! 員工10,sleep:10 等待了0(ms),開始吃飯了! 員工1,sleep:1 等待了9000(ms),開始吃飯了! 員工2,sleep:2 等待了8000(ms),開始吃飯了! 員工3,sleep:3 等待了6999(ms),開始吃飯了! 員工7,sleep:7 等待了3000(ms),開始吃飯了! 員工6,sleep:6 等待了4000(ms),開始吃飯了! 員工5,sleep:5 等待了5000(ms),開始吃飯了! 員工4,sleep:4 等待了6000(ms),開始吃飯了! 員工9,sleep:9 等待了999(ms),開始吃飯了! 員工8,sleep:8 等待了1999(ms),開始吃飯了!
第一次規則被打亂了,過了一會導遊重建了規則(cyclicBarrier.reset();
),接着又重來來了一次模擬等待吃飯的操做,正常了。
仍是舉例子說明一下:
CountDownLatch示例
主管至關於 CountDownLatch,幹活的小弟至關於作事情的線程。
老闆交給主管了一個任務,讓主管搞完以後當即上報給老闆。主管下面有10個小弟,接到任務以後將任務劃分爲10個小任務分給每一個小弟去幹,主管一直處於等待狀態(主管會調用await()
方法,此方法會阻塞當前線程),讓每一個小弟幹完以後通知一下主管(調用countDown()
方法通知主管,此方法會當即返回),主管等到全部的小弟都作完了,會被喚醒,從await()方法上甦醒,而後將結果反饋給老闆。期間主管會等待,會等待全部小弟將結果彙報給本身。
而CyclicBarrier是一批線程讓本身等待,等待全部的線程都準備好了,本身才能繼續。
高併發系列連載中,感興趣的加我微信itsoku,一塊兒交流,關注公衆號:路人甲Java,天天獲取最新文章,送年薪50萬java學習路線視頻!