CyclicBarrier是一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。
CyclicBarrier类似于CountDownLatch也是个计数器, 不同的是CyclicBarrier数的是调用了CyclicBarrier.await()进入等待的线程数, 当线程数达到了CyclicBarrier初始时规定的数目时,所有进入等待状态的线程被唤醒并继续。 CyclicBarrier就象它名字的意思一样,可看成是个障碍, 所有的线程必须到齐后才能一起通过这个障碍。 CyclicBarrier初始时还可带一个Runnable的参数,此Runnable任务在CyclicBarrier的数目达到后,所有其它线程被 唤醒前被执行。
构造方法摘要 |
---|
**[CyclicBarrier](http://www.cnblogs.com/java/util/concurrent/CyclicBarrier.html#CyclicBarrier(int))**(int parties) 创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,但它不会在每个 barrier 上执行预定义的操作。 |
**[CyclicBarrier](http://www.cnblogs.com/java/util/concurrent/CyclicBarrier.html#CyclicBarrier(int, java.lang.Runnable))**(int parties, [Runnable](http://www.cnblogs.com/java/lang/Runnable.html "java.lang 中的接口") barrierAction) 创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,并在启动 barrier 时执行给定的屏障操作,该操作由最后一个进入 barrier 的线程执行 |
方法摘要 | |
---|---|
int |
**[await](http://www.cnblogs.com/java/util/concurrent/CyclicBarrier.html#await())**() 在所有 参与者 )都已经在此 barrier 上调用 await 方法之前,将一直等待。 |
int |
**[await](http://www.cnblogs.com/java/util/concurrent/CyclicBarrier.html#await(long, java.util.concurrent.TimeUnit))**(long timeout, [TimeUnit](http://www.cnblogs.com/java/util/concurrent/TimeUnit.html "java.util.concurrent 中的枚举") unit) 在所有 参与者 )都已经在此屏障上调用 await 方法之前,将一直等待。 |
int |
**[getNumberWaiting](http://www.cnblogs.com/java/util/concurrent/CyclicBarrier.html#getNumberWaiting())**() 返回当前在屏障处等待的参与者数目。 |
int |
**[getParties](http://www.cnblogs.com/java/util/concurrent/CyclicBarrier.html#getParties())**() 返回要求启动此 barrier 的参与者数目。 |
boolean |
**[isBroken](http://www.cnblogs.com/java/util/concurrent/CyclicBarrier.html#isBroken())**() 查询此屏障是否处于损坏状态。 |
void |
**[reset](http://www.cnblogs.com/java/util/concurrent/CyclicBarrier.html#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。如果把上面的例子改成下面这样:
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 }
则结果如下:
线程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个已经到达,正在等候
**我最先执行*