这是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学习路线视频!