java多线程-CyclicBarrier

  • 介绍

  一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。 

  CyclicBarrier 支持一个可选的 Runnable 命令,在一组线程中的最后一个线程到达之后(但在释放所有线程之前),该命令只在每个屏障点运行一次。若在继续所有参与线程之前更新共享状态,此屏障操作 很有用。 

  • 主要方法
  • 1 //设置parties、count及barrierCommand属性。   
    2 CyclicBarrier(int):   
    3 //当await的数量到达了设定的数量后,首先执行该Runnable对象。   
    4 CyclicBarrier(int,Runnable):   
    5 //通知barrier已完成线程   
    6 await():  
  • 应用场景

  1:CyclicBarrier 表示大家彼此等待,大家集合好后才开始出发,分散活动后又在i指定地点集合碰面,这就好比整个公司的人员利用周末时间集体郊游一样,先各自从家出发到公司集合后,再同时出发到公园游玩,在指定地点集合后再同时开始就餐。

  代码:

 1 public class CyclicBarrierTest {
 2     public static void main(String[] args){
 3         ExecutorService pool = Executors.newCachedThreadPool();
 4         final CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
 5         
 6         for (int i = 0; i < 3; i++) {
 7             Runnable runnable = new Runnable() {
 8                 @Override
 9                 public void run(){
10                     try {
11                         Thread.sleep(new Random().nextInt(5000));
12                     } catch (InterruptedException e) {
13                         // TODO Auto-generated catch block
14                         e.printStackTrace();
15                     }
16                     System.out.println(Thread.currentThread().getName()+"到达地点一,当前等待人数为"+(cyclicBarrier.getNumberWaiting()+1)+(cyclicBarrier.getNumberWaiting()+1==3?"继续出发":"继续等待"));
17                     try {
18                         cyclicBarrier.await();//障碍等待点
19                     } catch (InterruptedException e) {
20                         // TODO Auto-generated catch block
21                         e.printStackTrace();
22                     } catch (BrokenBarrierException e) {
23                         // TODO Auto-generated catch block
24                         e.printStackTrace();
25                     }
26                     try {
27                         Thread.sleep(new Random().nextInt(5000));
28                     } catch (InterruptedException e) {
29                         // TODO Auto-generated catch block
30                         e.printStackTrace();
31                     }
32                     System.out.println(Thread.currentThread().getName()+"到达地点二,当前等待人数为"+(cyclicBarrier.getNumberWaiting()+1)+(cyclicBarrier.getNumberWaiting()+1==3?"继续出发":"继续等待"));
33                     try {
34                         cyclicBarrier.await();//障碍等待点
35                     } catch (InterruptedException e) {
36                         // TODO Auto-generated catch block
37                         e.printStackTrace();
38                     } catch (BrokenBarrierException e) {
39                         // TODO Auto-generated catch block
40                         e.printStackTrace();
41                     }
42                     try {
43                         Thread.sleep(new Random().nextInt(5000));
44                     } catch (InterruptedException e) {
45                         // TODO Auto-generated catch block
46                         e.printStackTrace();
47                     }
48                     System.out.println(Thread.currentThread().getName()+"到达地点三,当前等待人数为"+(cyclicBarrier.getNumberWaiting()+1)+(cyclicBarrier.getNumberWaiting()+1==3?"人齐了出发":"继续等待"));
49                     try {
50                         cyclicBarrier.await();//障碍等待点
51                     } catch (InterruptedException e) {
52                         // TODO Auto-generated catch block
53                         e.printStackTrace();
54                     } catch (BrokenBarrierException e) {
55                         // TODO Auto-generated catch block
56                         e.printStackTrace();
57                     }
58                 }
59             };
60             pool.execute(runnable);
61         }
62         pool.shutdown();
63     }
64 }

  执行结果:

1 pool-1-thread-3到达地点一,当前等待人数为1继续等待
2 pool-1-thread-1到达地点一,当前等待人数为2继续等待
3 pool-1-thread-2到达地点一,当前等待人数为3继续出发
4 pool-1-thread-1到达地点二,当前等待人数为1继续等待
5 pool-1-thread-3到达地点二,当前等待人数为2继续等待
6 pool-1-thread-2到达地点二,当前等待人数为3继续出发
7 pool-1-thread-3到达地点三,当前等待人数为1继续等待
8 pool-1-thread-2到达地点三,当前等待人数为2继续等待
9 pool-1-thread-1到达地点三,当前等待人数为3人齐了出发
View Code

  2:在某种需求中,比如一个大型的任务,常常需要分配好多子任务去执行,只有当所有子任务都执行完成时候,才能执行主任务,这时候,就可以选择CyclicBarrier了。

  代码:

 1 public class CyclicBarrierTest1 {
 2     public static void main(String[] args) {
 3         ExecutorService threadPool = Executors.newCachedThreadPool();
 4         CyclicBarrier barrier = new CyclicBarrier(5, new mainTask());
 5         for (int i = 0; i < 5; i++) {
 6             subTask subTask = new subTask(barrier);
 7             threadPool.execute(subTask);
 8         }
 9         threadPool.shutdown();
10     }
11 }
12 
13 class subTask implements Runnable{
14     private CyclicBarrier barrier;
15     
16     public subTask(CyclicBarrier barrier) {
17         super();
18         this.barrier = barrier;
19     }
20     @Override
21     public void run() {
22         System.out.println(Thread.currentThread().getName()+"正在执行");
23         try {
24             Thread.sleep(5000);
25         } catch (InterruptedException e) {
26             // TODO Auto-generated catch block
27             e.printStackTrace();
28         }
29         System.out.println(Thread.currentThread().getName()+"执行完毕,等待其他结果");
30         try {
31             barrier.await();
32         } catch (InterruptedException e) {
33             // TODO Auto-generated catch block
34             e.printStackTrace();
35         } catch (BrokenBarrierException e) {
36             // TODO Auto-generated catch block
37             e.printStackTrace();
38         }
39         
40     }
41 }
42 class mainTask implements Runnable{
43 
44     @Override
45     public void run() {
46         System.out.println("总任务执行完毕");
47     }
48     
49 }

  执行结果:

 1 pool-1-thread-2正在执行
 2 pool-1-thread-3正在执行
 3 pool-1-thread-1正在执行
 4 pool-1-thread-4正在执行
 5 pool-1-thread-5正在执行
 6 pool-1-thread-2执行完毕,等待其他结果
 7 pool-1-thread-5执行完毕,等待其他结果
 8 pool-1-thread-1执行完毕,等待其他结果
 9 pool-1-thread-4执行完毕,等待其他结果
10 pool-1-thread-3执行完毕,等待其他结果
11 总任务执行完毕
View Code

  另外,CyclicBarrier是可以重用的,它可以在使用完后继续使用,这就是Cyclic(循环)的意思。

 

posted @ 2016-02-24 22:05  ngulc  阅读(1128)  评论(0编辑  收藏  举报