二、Java多线程并发同步之CyclicBarrier

概述

CyclicBarrier:可循环屏障,允许一组线程全部等待的同步辅助工具。一组线程互相等待,直到所有线程都到达某个公共屏障点(也可以叫同步点) 。它可以在等待线程之后重新使用。这个屏障之所以用循环修饰,是因为在所有的线程释放彼此之后,这个屏障是可以重新使用的 。

CyclicBarrier支持一个可选的Runnable命令,在一组线程中的最后一个线程到达屏障点之后(但在释放所有线程之前),该命令只在所有线程到达屏障点之后运行一次,并且该命令由最后一个进入屏障点的线程执行。

业务场景

需要所有的子任务都完成时,才执行主任务,这个时候就可以选择使用CyclicBarrier。 例如,多线程计算数据,最后合并汇总计算的场景;长途汽车等人到齐了才发车的场景,王者荣耀5V5时,需要10个人的进度都为100%时才能进入游戏等等场景都可以使用CyclicBarrier实现。

下面介绍一个5个人约好去五星级大酒店聚餐场景:5个人约好去聚餐,由于每个人家到酒店的距离不一样,所以需要等所有人到齐后,才能开餐吃饭,并且规定谁最后一个到,就请大家一起去按摩,然后去吃饭。

实现

CyclicBarrier(int parties):创建一个给定数量线程的循环屏障,当到达同步点时,不执行预先定义的动作

CyclicBarrier(int parties, Runnable barrierAction):创建一个给定数量线程的循环屏障,当到达同步点时,执行 Runnable方法

await():进行阻塞等待 ,直到满足下列条件时,继续执行:

  • 等待的线程数达到parties时,所有到达的线程将被释放,继续向下执行。
  • 当前线程被中断,抛出InterruptedException异常,并停止等待,继续执行。
  • 其他等待的线程被中断(interrupt),当前线程会抛出BrokenBarrierException异常,并停止等待,继续执行。
  • 其他等待的线程超时,当前线程会抛出BrokenBarrierException异常,并停止等待,继续执行。
  • 其他线程调用reset()方法,当前线程会抛出BrokenBarrierException异常,并停止等待,继续执行。

reset():重置,使CyclicBarrier回归初始状态

getNumberWaiting():获取正在等待的线程数量。

/**
 * CyclicBarrier : 可循环的屏障,让一组线程到达一个同步点后再一起继续运行,在其中任意一个线程未达到同步点,其他到达的线程均会被阻塞。
 * 业务场景: 5个人约好去五星级大酒店聚餐
 */
public class CyclicBarrierTest implements Runnable {
	private ExecutorService es = Executors.newCachedThreadPool();
	private CyclicBarrier cyclicBarrier = new CyclicBarrier(5, this); // 拦截线程为5

	//达到同步点后执行方法
	@Override
	public void run() {
		System.out.println("吃饭前先一起去按摩");
	}

	//实现任务
	public void invoke() {
		// 5个线程,模拟5个人
		for (int i = 0; i < 5; i++) {
			final String user = "user"+(i+1);
			es.execute(new Runnable() {
				@Override
				public void run() {
					try {
						Thread.sleep((long)(Math.random()*10000));   //模拟去酒店,每个人都不一样
						System.out.println(user+"---到达酒店,当前有"+(cyclicBarrier.getNumberWaiting()+1)+"个人到达");
						
						cyclicBarrier.await(); // 等待所有人到酒店
						
						System.out.println(user + "---所有人到齐,吃饭去了。。。");
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			});
		}
	}

	public static void main(String[] args) {
		CyclicBarrierTest service = new CyclicBarrierTest();
		service.invoke();
	}
}

输出结果:

user4---到达酒店,当前有1个人到达
user2---到达酒店,当前有2个人到达
user3---到达酒店,当前有3个人到达
user1---到达酒店,当前有4个人到达
user5---到达酒店,当前有5个人到达
吃饭前先一起去按摩
user5---所有人到齐,吃饭去了。。。
user4---所有人到齐,吃饭去了。。。
user1---所有人到齐,吃饭去了。。。
user3---所有人到齐,吃饭去了。。。
user2---所有人到齐,吃饭去了。。。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值