30、CyclicBarrier的使用

CyclicBarrier是一个同步工具类,它允许一组线程互相等待,直到到达某个公共屏障点。
与CountDownLatch不同的是该barrier在释放等待线程后可以重用,所以称它为循环(Cyclic)的屏障(Barrier)。

CyclicBarrier API:

1、第一个默认构造方法,参数表示拦截的线程数量。

2、第二个构造方法:由于线程之前的调度是由CPU决定的,所以默认的构造方法无法设置线程执行优先级,CyclicBarrier提供一个更高级的构造函数CyclicBarrier(int parties, Runnable barrierAction),用于在线程到达同步点时,优先执行线程barrierAction,这样可以更加方便的处理一些负责的业务场景。
3、await实现
   创建CyclicBarrier后,每个线程调用await方法告诉CyclicBarrier自己已经到达同步点,然后当前线程被阻塞

比较CountDownLatch和CyclicBarrier:
 1)CountDownLatch:一个线程(或者多个),等待另外N个线程完成某个事情之后才能执行;CyclicBarrier:N个线程相互等待,            任何一个线程完成之前,所有的线程都必须等待。
 2)CountDownLatch:一次性的;CyclicBarrier:可以重复使用。
 3)CountDownLatch基于AQS;CyclicBarrier基于锁和Condition。本质上都是依赖于volatile和CAS实现的。

对于CountDownLatch来说,重点是“一个线程(多个线程)等待”,而其他的N个线程在完成“某件事情”之后,可以终止,也可以等待。而对于CyclicBarrier,重点是多个线程,在任意一个线程没有完成,所有的线程都必须等待。

CountDownLatch是计数器,线程完成一个记录一个,只不过计数不是递增而是递减,而CyclicBarrier更像是一个阀门,需要所有线程都到达,阀门才能打开,然后继续执行。
 

下面举例说明CyclicBarrier的使用场景。

比如:篮球三人一组才能开站,等到三个人,他们一组就去打篮球了。

public class Test {
	private static final ThreadPoolExecutor threadPool=new ThreadPoolExecutor(3,10,60,TimeUnit.SECONDS,new LinkedBlockingQueue<Runnable>());
 	//CountDownLatch  countdl=new CountDownLatch(3);
 	CyclicBarrier   countdl =new CyclicBarrier(3,new Runnable() {
		public void run()
		{
			System.out.println("开始打篮球了");
		}});

	public static void main(String[] args) {
		
		final Test  test=new Test();

		Thread  zhansan=new Thread(new Player(test.countdl,"zhansan"));
		Thread  zhaner=new Thread(new Player(test.countdl,"zhaner"));
		Thread  zhanyi=new Thread(new Player(test.countdl,"zhanyi"));
		Thread  zhansan2=new Thread(new Player(test.countdl,"zhansan2"));
		Thread  zhaner2=new Thread(new Player(test.countdl,"zhaner2"));
		Thread  zhanyi2=new Thread(new Player(test.countdl,"zhanyi2"));
		
		threadPool.execute(zhansan);
		threadPool.execute(zhaner);
		threadPool.execute(zhanyi);
		threadPool.execute(zhansan2);
		threadPool.execute(zhaner2);
		threadPool.execute(zhanyi2);
	}
	
	
	

}

class   Player  implements  Runnable{
	private  CyclicBarrier  ctd;
	private  String  name;
	public Player(CyclicBarrier  ctd,String  name){
		this.ctd=ctd;
		this.name=name;
	}

	public void run() {
		try {
			System.out.println(this.name+",开始出发了,"+new Date());
			Thread.sleep(Math.round(1000));
			ctd.await();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

运行结果如下: 

zhansan,开始出发了,Thu Jul 19 21:10:44 CST 2018
zhanyi,开始出发了,Thu Jul 19 21:10:44 CST 2018
zhaner,开始出发了,Thu Jul 19 21:10:44 CST 2018
开始打篮球了
zhansan2,开始出发了,Thu Jul 19 21:10:45 CST 2018
zhanyi2,开始出发了,Thu Jul 19 21:10:45 CST 2018
zhaner2,开始出发了,Thu Jul 19 21:10:45 CST 2018
开始打篮球了

猜你喜欢

转载自blog.csdn.net/zhangkang65/article/details/81122890
今日推荐