并发库应用之八 & 循环路障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应用