CyclicBarrier是一个同步辅助类,它容许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 颇有用。由于该 barrier 在释放等待线程后能够重用,因此称它为循环 的 barrier。html
CyclicBarrier相似于CountDownLatch也是个计数器, 不一样的是CyclicBarrier数的是调用了CyclicBarrier.await()进入等待的线程数, 当线程数达到了CyclicBarrier初始时规定的数目时,全部进入等待状态的线程被唤醒并继续。 CyclicBarrier就象它名字的意思同样,可当作是个障碍, 全部的线程必须到齐后才能一块儿经过这个障碍。 CyclicBarrier初始时还可带一个Runnable的参数,此Runnable任务在CyclicBarrier的数目达到后,全部其它线程被唤醒前被执行。java
构造方法摘要 |
---|
CyclicBarrier(int parties) 建立一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,但它不会在每一个 barrier 上执行预约义的操做。 |
CyclicBarrier(int parties, Runnable barrierAction) 建立一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,并在启动 barrier 时执行给定的屏障操做,该操做由最后一个进入 barrier 的线程执行 |
方法摘要 | |
---|---|
int |
await() 在全部 参与者 都已经在此 barrier 上调用 await 方法以前,将一直等待。 |
int |
await(long timeout, TimeUnit unit) 在全部 参与者 都已经在此屏障上调用 await 方法以前,将一直等待。 |
int |
getNumberWaiting() 返回当前在屏障处等待的参与者数目。 |
int |
getParties() 返回要求启动此 barrier 的参与者数目。 |
boolean |
isBroken() 查询此屏障是否处于损坏状态。 |
void |
reset() 将屏障重置为其初始状态。 |
1 package com.thread; 2 import java.util.concurrent.CyclicBarrier; 3 import java.util.concurrent.ExecutorService; 4 import java.util.concurrent.Executors; 5 import java.util.concurrent.Semaphore; 6 7 public class CyclicBarrierTest { 8 9 public static void main(String[] args) { 10 ExecutorService service = Executors.newCachedThreadPool(); 11 final CyclicBarrier cb = new CyclicBarrier(3);//建立CyclicBarrier对象并设置3个公共屏障点 12 for(int i=0;i<3;i++){ 13 Runnable runnable = new Runnable(){ 14 public void run(){ 15 try { 16 Thread.sleep((long)(Math.random()*10000)); 17 System.out.println("线程" + Thread.currentThread().getName() + 18 "即将到达集合地点1,当前已有" + cb.getNumberWaiting() + "个已经到达,正在等候"); 19 cb.await();//到此若是没有达到公共屏障点,则该线程处于等待状态,若是达到公共屏障点则全部处于等待的线程都继续往下运行 20 21 Thread.sleep((long)(Math.random()*10000)); 22 System.out.println("线程" + Thread.currentThread().getName() + 23 "即将到达集合地点2,当前已有" + cb.getNumberWaiting() + "个已经到达,正在等候"); 24 cb.await(); 25 Thread.sleep((long)(Math.random()*10000)); 26 System.out.println("线程" + Thread.currentThread().getName() + 27 "即将到达集合地点3,当前已有" + cb.getNumberWaiting() + "个已经到达,正在等候"); 28 cb.await(); 29 } catch (Exception e) { 30 e.printStackTrace(); 31 } 32 } 33 }; 34 service.execute(runnable); 35 } 36 service.shutdown(); 37 } 38 }
线程pool-1-thread-1即将到达集合地点1,当前已有0个已经到达,正在等候 线程pool-1-thread-3即将到达集合地点1,当前已有1个已经到达,正在等候 线程pool-1-thread-2即将到达集合地点1,当前已有2个已经到达,正在等候 线程pool-1-thread-3即将到达集合地点2,当前已有0个已经到达,正在等候 线程pool-1-thread-2即将到达集合地点2,当前已有1个已经到达,正在等候 线程pool-1-thread-1即将到达集合地点2,当前已有2个已经到达,正在等候 线程pool-1-thread-1即将到达集合地点3,当前已有0个已经到达,正在等候 线程pool-1-thread-3即将到达集合地点3,当前已有1个已经到达,正在等候 线程pool-1-thread-2即将到达集合地点3,当前已有2个已经到达,正在等候
若是在构造CyclicBarrier对象的时候传了一个Runnable对象进去,则每次到达公共屏障点的时候都最早执行这个传进去的Runnable,而后再执行处于等待的Runnable。若是把上面的例子改为下面这样:dom
1 package com.thread; 2 import java.util.concurrent.CyclicBarrier; 3 import java.util.concurrent.ExecutorService; 4 import java.util.concurrent.Executors; 5 import java.util.concurrent.Semaphore; 6 7 public class CyclicBarrierTest { 8 9 public static void main(String[] args) { 10 ExecutorService service = Executors.newCachedThreadPool(); 11 //final CyclicBarrier cb = new CyclicBarrier(3);//建立CyclicBarrier对象并设置3个公共屏障点 12 final CyclicBarrier cb = new CyclicBarrier(3,new Runnable(){ 13 @Override 14 public void run() { 15 System.out.println("********我最早执行***********"); 16 } 17 }); 18 for(int i=0;i<3;i++){ 19 Runnable runnable = new Runnable(){ 20 public void run(){ 21 try { 22 Thread.sleep((long)(Math.random()*10000)); 23 System.out.println("线程" + Thread.currentThread().getName() + 24 "即将到达集合地点1,当前已有" + cb.getNumberWaiting() + "个已经到达,正在等候"); 25 cb.await();//到此若是没有达到公共屏障点,则该线程处于等待状态,若是达到公共屏障点则全部处于等待的线程都继续往下运行 26 27 Thread.sleep((long)(Math.random()*10000)); 28 System.out.println("线程" + Thread.currentThread().getName() + 29 "即将到达集合地点2,当前已有" + cb.getNumberWaiting() + "个已经到达,正在等候"); 30 cb.await(); //这里CyclicBarrier对象又能够重用 31 Thread.sleep((long)(Math.random()*10000)); 32 System.out.println("线程" + Thread.currentThread().getName() + 33 "即将到达集合地点3,当前已有" + cb.getNumberWaiting() + "个已经到达,正在等候"); 34 cb.await(); 35 } catch (Exception e) { 36 e.printStackTrace(); 37 } 38 } 39 }; 40 service.execute(runnable); 41 } 42 service.shutdown(); 43 } 44 }
则结果以下:ide
线程pool-1-thread-1即将到达集合地点1,当前已有0个已经到达,正在等候 线程pool-1-thread-3即将到达集合地点1,当前已有1个已经到达,正在等候 线程pool-1-thread-2即将到达集合地点1,当前已有2个已经到达,正在等候 ********我最早执行*********** 线程pool-1-thread-1即将到达集合地点2,当前已有0个已经到达,正在等候 线程pool-1-thread-3即将到达集合地点2,当前已有1个已经到达,正在等候 线程pool-1-thread-2即将到达集合地点2,当前已有2个已经到达,正在等候 ********我最早执行*********** 线程pool-1-thread-1即将到达集合地点3,当前已有0个已经到达,正在等候 线程pool-1-thread-3即将到达集合地点3,当前已有1个已经到达,正在等候 线程pool-1-thread-2即将到达集合地点3,当前已有2个已经到达,正在等候 ********我最早执行***********