Java核心-多线程(7)-并发控制器-CyclicBarrier同步屏障

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,准备结束!
他们都准备好了,那就开跑吧
3
2
1
0
go!!!
运动员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()方法;

原文地址:https://www.cnblogs.com/leeethan/p/10680835.html