JUC学习笔记 -- (11) CyclicBarrier介绍及其与CountDownLatch的区别

CyclicBarrier是多线程中一个常用的辅助类,主要用于线程组内部之间的线程的相互等待问题。

 CyclicBarrier根据英文拆分翻译可翻译为:可循环利用的屏障。顾名思义,首先,便是可重复利用,说明该类创建的对象可以复用;其次,屏障则体现了该类的原理:每个线程执行时,都会碰到一个屏障,直到所有线程执行结束,然后屏障便会打开,使所有线程继续往下执行。大致功效可以理解为:等待集合继续执行。

        这里介绍CyclicBarrier的两个构造函数:CyclicBarrier(int parties)和CyclicBarrier(int parties, Runnable barrierAction) :前者只需要声明需要拦截的线程数即可,而后者还需要定义一个等待所有线程到达屏障优先执行的Runnable对象。

        实现原理:在CyclicBarrier的内部定义了一个Lock对象,每当一个线程调用await方法时,将拦截的线程数减1,然后判断剩余拦截数是否为初始值parties,如果不是,进入Lock对象的条件队列等待。如果是,执行barrierAction对象的Runnable方法,然后将锁的条件队列中的所有线程放入锁等待队列中,这些线程会依次的获取锁、释放锁。

      举例说明:如果一个寝室四个人约好了去球场打球,由于四个人准备工作不同,所以约好在楼下集合,并且四个人集合好之后再依次前往球场(蛋疼的需求,测试需要,勿见怪)。

public class TestCyclicBarrier {
	private final static ThreadPoolExecutor threadPool = 
			new ThreadPoolExecutor(4, 10, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
	private final static CyclicBarrier barry = new CyclicBarrier(4, new Runnable() {
		int num = 1;
		@Override
		public void run() {
			if(num == 1){
				System.out.println("人员在楼下集合完毕!");
				num++;
			}else if(num == 2){
				System.out.println("人员在操场集合完毕!");
			}
			System.out.println("====================");
		}
	});	
	public static void main(String[] args) {
		String[] names = {"小明","小红","小华","小黑"};
		for(int i=0;i<4;i++){
			threadPool.execute(new CyclicBarrierDemo(names[i],barry));
		}
		try
		{
			Thread.sleep(1000);
			System.out.println("四个人一起到达球场,现在开始打球");
		}
		catch(InterruptedException e)
		{
			e.printStackTrace();
		}
		threadPool.shutdown();
	}
	
}

class CyclicBarrierDemo extends Thread{
	private String name;
	private CyclicBarrier barry;
	public CyclicBarrierDemo(String name,CyclicBarrier barry) {
		this.name = name;
		this.barry = barry;
	}
	@Override
	public void run() {
		
		try {
			System.out.println(name+"从宿舍出发!");
			Thread.sleep(200);
			barry.await();
			System.out.println(name+"从楼下出发!");
			Thread.sleep(200);
			//复用
			barry.await();
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

运行程序,得到如下结果:

以上便是CyclicBarrier使用实例,通过await()方法对线程的拦截,拦截数加1,当拦截数为初始的parties,首先执行了barrierAction,然后对拦截的线程队列依次进行获取锁释放锁。可以看出CyclicBarriers是可以重复使用的。

CountDownLatch和CyclicBarrier的比较

1.CountDownLatch是线程组之间的等待,即一个(或多个)线程等待N个线程完成某件事情之后再执行;而CyclicBarrier则是线程组内的等待,即每个线程相互等待,即N个线程都被拦截之后,然后依次执行。

2.CountDownLatch是减计数方式,而CyclicBarrier是加计数方式。

3.CountDownLatch计数为0无法重置,而CyclicBarrier计数达到初始值,则可以重置。

4.CountDownLatch不可以复用,而CyclicBarrier可以复用。

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值