并发库应用之八 & 循环路障CyclicBarrier应用

  JDK包位置:java.util.concurrent.CyclicBarrier

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

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

对应构造方法摘要:

  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()                        将屏障重置为其初始状态。

  案例应用:组织人员(线程)郊游,约定一个时间地点(路障),人员陆续到达地点,等所有人员全部到达,开始到公园各玩各的,再到约定时间去食堂吃饭,等所有人到齐开饭……;依据此思想,用代码实现:三个线程干完各自的任务,在不同的时刻到达集合点后,就可以接着忙各自的工作去了,再到达新的集合点,再去忙各自的工作,到达集合点了用 CyclicBarrier 对象的 await 方法表示。

 1 import java.util.concurrent.CyclicBarrier;
 2 import java.util.concurrent.ExecutorService;
 3 import java.util.concurrent.Executors;
 4 
 5 public class CyclicBarrierTest {
 6     public static void main(String[] args) {
 7         //线程数动态变化,来一个就产生一个线程
 8         ExecutorService service = Executors.newCachedThreadPool();
 9         final CyclicBarrier cb = new CyclicBarrier(3); //包含有3个线程的容量
10         for (int i = 0; i < 3; i++) { //3个集合地点
11             Runnable runnable = new Runnable() {
12                 public void run() {
13                     try {
14                         Thread.sleep((long) (Math.random() * 5000));
15                         System.out.println(String.format("线程%s已经到达集合地点【1】,当前已有%d个已经到达,正在等候", Thread.currentThread().getName(), cb.getNumberWaiting()+1));
16                         cb.await();
17 
18                         Thread.sleep((long) (Math.random() * 5000));
19                         System.out.println(String.format("线程%s已经到达集合地点【2】,当前已有%d个已经到达,正在等候", Thread.currentThread().getName(), cb.getNumberWaiting()+1));
20                         cb.await();
21 
22                         Thread.sleep((long) (Math.random() * 5000));
23                         System.out.println(String.format("线程%s已经到达集合地点【3】,当前已有%d个已经到达,正在等候", Thread.currentThread().getName(), cb.getNumberWaiting()+1));
24                         cb.await();
25                     } catch (Exception e) {
26                         e.printStackTrace();
27                     }
28                 }
29             };
30             service.execute(runnable);
31         }
32         service.shutdown();
33     }
34 }

运行以上代码打印结果如下所示:

  

 提示:欢迎继续参看我相关的下一篇博客:并发库应用之九 & 到时计数器CountDownLatch应用

posted @ 2017-03-09 15:59  星火燎原智勇  阅读(388)  评论(0编辑  收藏