1.基本概念
中文译本同步屏障,同样来自jdk并发工具包中一个并发控制器,它的使用和CountDownLatch有点相似,能够完成某些相同并发场景,但是它们却不相同。2.抽象模型
主要用来实现多个线程同步,同步后可能唤醒另外一个任务,然后继续执行线程后面的任务。CountDownLatch抽象模型却是一个或多个线程通知某个或多个线程,它没有同步功能。3.使用场景
田径比赛, 虽然上一篇文章使用CountDownLatch也能实现,但是我觉得这里却使用同步屏障更简单点。4.CyclicBarrier使用api
java new CyclicBarrier(int parties); //创建同步屏障,仅仅启动同步作用,中间没有需要执行的任务。
java new CyclicBarrier(int parties, Runnable barrierAction); //创建同步屏障,不仅同步,而且中间有任务需要执行。
java cyclicBarrier.await(); //调用一次,parties就会减1,直到变为0时,执行barrierAction任务后(配置情况下),然后执行此代码的线程才能停止阻塞,继续执行。
java ps:因为使用CyclicBarrier的线程都会阻塞在await方法上,所以在线程池中使用CyclicBarrier时要特别小心,如果线程池的线程过少,那么就会发生死锁了。
5.使用示例(田径比赛)
public static void main(String[] args) { ExecutorService executor = Executors.newFixedThreadPool(3); final CyclicBarrier startBarrier = new CyclicBarrier(3, new Runnable() { @Override public void run() { try { System.out.println("他们都准备好了,那就开跑吧"); System.out.println("3"); Thread.sleep(1000); System.out.println("2"); Thread.sleep(1000); System.out.println("1"); Thread.sleep(1000); System.out.println("0"); System.out.println("go!!!"); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); CyclicBarrier endBarrier = new CyclicBarrier(3, new Runnable() { @Override public void run() { System.out.println("都到达了终点,比赛结束"); } }); for(int i=3;i>0;i--){ final int num = i; Runnable runnable = new Runnable() { @Override public void run() { try { int time = (int)(Math.random()*1000); Thread.sleep(time); System.out.println("运动员" + num + "号,准备了" + time + "ms,准备结束!"); startBarrier.await(); System.out.println("运动员" + num + "号,开始跑了"); int runtime = (int)(Math.random()*10000); Thread.sleep(runtime); System.out.println("运动员" + num + "号,用时:" + runtime + "ms"); endBarrier.await(); } catch (Exception e) { e.printStackTrace(); } } }; executor.submit(runnable); } }
执行结果
运动员1号,准备了580ms,准备结束!运动员3号,准备了866ms,准备结束!运动员2号,准备了878ms,准备结束!他们都准备好了,那就开跑吧3210go!!!运动员2号,开始跑了运动员1号,开始跑了运动员3号,开始跑了运动员2号,用时:2008ms运动员3号,用时:5587ms运动员1号,用时:6634ms都到达了终点,比赛结束
6.和CountDownLatch的区别
<1>CountDownLatch能唤醒多个线程,而CyclicBarrier只能唤醒一个线程; <2>一个线程或多个线程(A)使用CountDownLatch通知另外一个或多个线程(B),A线程之间不会有同步功能,需要多个latch才能实现同步功能;而CyclicBarrier能同步A线程组的执行步骤; <3>CountDownLatch是一次性的,不能重置,而CyclicBarrier不是,它有reset()方法;