首页 > 代码库 > Java并发程序设计(19)并发锁之循环障碍CyclicBarrier
Java并发程序设计(19)并发锁之循环障碍CyclicBarrier
1.1. 循环障碍CyclicBarrier
CyclicBarrier用于多个线程在某个同步点达到同步。在所有线程都到达该同步点之前,已经到达同步点的线程会等待其他线程。简单理解可以说CyclicBarrier跟一个旅游团出去旅游是类似的。在旅游团所有队员都到达出发集合地点之前,提前达到的队员只能在集合地点等待其他队员。当所有队员都达到后就可以出发了。循环障碍可以类似于旅游团在每个集合地点都这么等待一次,然后统一前往下一个景点。
package com.test.concurrence; import java.util.Date; import java.util.Random; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class CyclicBarrierTest { public static void main(String[] args) { //总共10个parties:这里是10个线程。 final CyclicBarrier cyclicBarrier = new CyclicBarrier(10); ExecutorService executorService = Executors.newFixedThreadPool(10); for(int i=0;i<10;i++){ executorService.submit(new Runnable(){ @Override public void run() { try { //随机暂停一段时间,模拟提前达到。 Thread.sleep(1000* new Random().nextInt(20)); System.out.println("waiting:" + cyclicBarrier.getNumberWaiting() + " , parties:" + cyclicBarrier.getParties() + " , " + new Date()); //提前达到的线程等待还没到达的线程。 cyclicBarrier.await(); } catch (InterruptedException | BrokenBarrierException e) { e.printStackTrace(); } //所有线程都到了。 System.out.println("ready:" + cyclicBarrier.getNumberWaiting() + " , parties:" + cyclicBarrier.getParties() + " , " + new Date()); } }); } executorService.shutdown(); } }
运行结果如下:
waiting:0 , parties:10 , Sat Mar 18 22:40:06 CST 2017
waiting:0 , parties:10 , Sat Mar 18 22:40:06 CST 2017
waiting:0 , parties:10 , Sat Mar 18 22:40:06 CST 2017
waiting:3 , parties:10 , Sat Mar 18 22:40:10 CST 2017
waiting:4 , parties:10 , Sat Mar 18 22:40:13 CST 2017
waiting:5 , parties:10 , Sat Mar 18 22:40:19 CST 2017
waiting:5 , parties:10 , Sat Mar 18 22:40:19 CST 2017
waiting:7 , parties:10 , Sat Mar 18 22:40:22 CST 2017
waiting:8 , parties:10 , Sat Mar 18 22:40:23 CST 2017
waiting:8 , parties:10 , Sat Mar 18 22:40:23 CST 2017
ready:0 , parties:10 , Sat Mar 18 22:40:23 CST 2017
ready:0 , parties:10 , Sat Mar 18 22:40:23 CST 2017
ready:0 , parties:10 , Sat Mar 18 22:40:23 CST 2017
ready:0 , parties:10 , Sat Mar 18 22:40:23 CST 2017
ready:0 , parties:10 , Sat Mar 18 22:40:23 CST 2017
ready:0 , parties:10 , Sat Mar 18 22:40:23 CST 2017
ready:0 , parties:10 , Sat Mar 18 22:40:23 CST 2017
ready:0 , parties:10 , Sat Mar 18 22:40:23 CST 2017
ready:0 , parties:10 , Sat Mar 18 22:40:23 CST 2017
ready:0 , parties:10 , Sat Mar 18 22:40:23 CST 2017
CyclicBarrier的构造函数可以接收一个Runnable对象,当所有线程达到后就会执行此对象的run方法。
package com.test.concurrence; import java.util.Date; import java.util.Random; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class CyclicBarrierTest2 { public static void main(String[] args) { final CyclicBarrier cyclicBarrier = new CyclicBarrier(10 , new Runnable(){ @Override public void run() { System.out.println("ready " + new Date()); } }); ExecutorService executorService = Executors.newFixedThreadPool(10); for(int i=0;i<10;i++){ executorService.submit(new Runnable(){ @Override public void run() { try { Thread.sleep(1000* new Random().nextInt(20)); System.out.println("waiting:" + cyclicBarrier.getNumberWaiting() + " , parties:" + cyclicBarrier.getParties() + " , " + new Date()); cyclicBarrier.await(); } catch (InterruptedException | BrokenBarrierException e) { e.printStackTrace(); } } }); } executorService.shutdown(); } }
waiting:0 , parties:10 , Sat Mar 18 22:59:54 CST 2017
waiting:1 , parties:10 , Sat Mar 18 22:59:58 CST 2017
waiting:2 , parties:10 , Sat Mar 18 22:59:59 CST 2017
waiting:3 , parties:10 , Sat Mar 18 23:00:01 CST 2017
waiting:4 , parties:10 , Sat Mar 18 23:00:02 CST 2017
waiting:5 , parties:10 , Sat Mar 18 23:00:03 CST 2017
waiting:6 , parties:10 , Sat Mar 18 23:00:06 CST 2017
waiting:7 , parties:10 , Sat Mar 18 23:00:07 CST 2017
waiting:8 , parties:10 , Sat Mar 18 23:00:08 CST 2017
waiting:9 , parties:10 , Sat Mar 18 23:00:11 CST 2017
ready Sat Mar 18 23:00:11 CST 2017
Java并发程序设计(19)并发锁之循环障碍CyclicBarrier