java障碍器 CyclicBarrier

五迷三道 提交于 2020-01-07 15:39:28

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

     Java5中,添加了障碍器类,为了适应一种新的设计需求,比如一个大型的任务,常常需要分配好多子任务去执行,只有当所有子任务都执行完成时候,才能执行主任务,这时候,就可以选择障碍器了。
障碍器是多线程并发控制的一种手段

      一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。 

     CyclicBarrier 支持一个可选的 Runnable 命令,在一组线程中的最后一个线程到达之后(但在释放所有线程之前),该命令只在每个屏障点运行一次。若在继续所有参与线程之前更新共享状态,此屏障操作 很有用。 
   CountDownLatch介绍:http://my.oschina.net/jielucky/blog/157946

  •  Java线程:新特征-障碍器  -主线程   
package com.thread.cyclicBarrier;

/**
 * Java线程:新特征-障碍器  -主线程
 * @author wangjie
 *
 */
public class MainTask implements Runnable {

	@Override
	public void run() {
		System.out.println("主线程执行了");
	}

}
  •  Java线程:新特征-障碍器  -主线程
package com.lucky.concurrent.cyclicBarrier;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

/**
 * Java线程:新特征-障碍器 -子线程
 * 
 * @author wangjie
 * 
 */
public class ChildTask extends Thread {
	private CyclicBarrier cb;
	private static int index = 0;

	ChildTask(CyclicBarrier cb) {
		this.cb = cb;
	}

	@Override
	public void run() {
		try {
			if (index >= 2) {
				Thread.sleep(3000);
			}
			index++;
			System.out.println("子线程执行完毕,通知主线程");
			// 注:这里parties里的计数在运行时当调用CyclicBarrier:await()时,计数就加1,一直加到初始的值
			cb.await(); // 通知障碍器已经完成
			System.out.println("一定要等到主线程执行之后才会执行   awati() 下面的 代码");
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (BrokenBarrierException e) {
			e.printStackTrace();
		}
	}
}

  • Java线程:新特征-障碍器 <testClass>
package com.thread.cyclicBarrier;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/** 
* Java线程:新特征-障碍器 
* 
* @author wangjie 2013-08-26 17:03:10 
*/ 
public class TestCyclicBarrier {
	public void run() {
		// 创建障碍器,并设置MainTask为所有定数量的线程都达到障碍点时候所要执行的任务(Runnable)
		CyclicBarrier cb = new CyclicBarrier(4, new MainTask());
		ExecutorService pool = Executors.newCachedThreadPool();
		pool.execute(new ChildTask(cb));
		pool.execute(new ChildTask(cb));
		pool.execute(new ChildTask(cb));
		pool.execute(new ChildTask(cb));
		pool.shutdown();
//		pool.shutdownNow();//有线程还没执行完,不能立即停止。只能调用shutdown()
	}

	public static void main(String[] args) {
		new TestCyclicBarrier().run();
	}
}

执行结果可以看出,所有子任务完成的时候,主任务执行了,达到了控制的目标。
注:这里parties里的计数在运行时当调用CyclicBarrier:await()时,计数就加1,一直加到初始的值。
以下比方是摘录其他文章:

CountDownLatch 是计数器, 线程完成一个就记一个, 就像 报数一样, 只不过是递减的.

CyclicBarrier更像一个水闸, 线程执行就想水流, 在水闸处都会堵住, 等到水满(线程到齐)了, 才开始泄流. PS:这个形容很到位滴。





易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!