15-Java5的CyclicBarrier同步工具

 

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

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

 

范例:有A、B、C三个人,他们约好周末去玩,计划各自先从家出发到集合点1集合,然后一起去集合点2吃饭,最后去集合点3唱歌。

注意:假设三个人都是各自开车去,有先后到达的情况。

package cn.itcast.demo.thread;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReentrantLock;

public class CyclicBarrierTest {
	public static void main(String[] args) {
		// 创建锁
		final ReentrantLock rtLock = new ReentrantLock();
		// 创建线程池对象
		ExecutorService executorService = Executors.newCachedThreadPool();
		// 创建3个线程同步类对象【即3个线程到达之后才开始执行任务】
		final CyclicBarrier cb = new CyclicBarrier(3);
		// 开启3个线程
		for (int i=0; i<3; i++) {
			Runnable runnable = new Runnable() {
				@Override
				public void run() {
					try {
						rtLock.lock();
						// 这是模拟线程从出发到到达集合点的过程的所花费的时间
						Thread.sleep((long)Math.random()*10000);
						System.out.println("线程[ " + Thread.currentThread().getName() 
								+ " ]即将到达集合点1,当前已有[ " + (cb.getNumberWaiting()+1) 
								+ " ]个线程已经到达," + (cb.getNumberWaiting()==2?"人到齐了,继续走啊!":"正在等候...")); 
						rtLock.unlock();
						// 只有三个线程都到了集合点1之后才继续执行下面的代码,否则就await(),继续等待...
						cb.await();
						
						rtLock.lock();
						// 如果三个线程都到达了集合点1之后,才开始向集合点2出发
						Thread.sleep((long)Math.random()*10000);
						System.out.println("线程[ " + Thread.currentThread().getName() 
								+ " ]即将到达集合点2,当前已有[ " + (cb.getNumberWaiting()+1) 
								+ " ]个线程已经到达," + (cb.getNumberWaiting()==2?"人到齐了,继续走啊!":"正在等候...")); 
						rtLock.unlock();
						// 同样,只有三个都到之后才会向集合点3出发,否则只能等待...
						cb.await();
						
						rtLock.lock();
						// 三个都到大集合点2之后,继续向集合点3出发
						Thread.sleep((long)Math.random()*10000);
						System.out.println("线程[ " + Thread.currentThread().getName() 
								+ " ]即将到达集合点3,当前已有[ " + (cb.getNumberWaiting()+1) 
								+ " ]个线程已经到达," + (cb.getNumberWaiting()==2?"人到齐了,继续走啊!":"正在等候..."));
					} catch (Exception e) {
						e.printStackTrace();
					} finally {
						rtLock.unlock();
						try {
							cb.await();
						} catch (Exception e) {
							e.printStackTrace();
						} 
					}
				}
			};
			// 将每个线程添加到线程池中
			executorService.execute(runnable);
		}
		// 结束所有线程
		executorService.shutdown();
	}
}

 

打印结果:

线程[ pool-1-thread-1 ]即将到达集合点1,当前已有[ 1 ]个线程已经到达,正在等候...
线程[ pool-1-thread-3 ]即将到达集合点1,当前已有[ 2 ]个线程已经到达,正在等候...
线程[ pool-1-thread-2 ]即将到达集合点1,当前已有[ 3 ]个线程已经到达,人到齐了,继续走啊!
线程[ pool-1-thread-2 ]即将到达集合点2,当前已有[ 1 ]个线程已经到达,正在等候...
线程[ pool-1-thread-1 ]即将到达集合点2,当前已有[ 2 ]个线程已经到达,正在等候...
线程[ pool-1-thread-3 ]即将到达集合点2,当前已有[ 3 ]个线程已经到达,人到齐了,继续走啊!
线程[ pool-1-thread-3 ]即将到达集合点3,当前已有[ 1 ]个线程已经到达,正在等候...
线程[ pool-1-thread-2 ]即将到达集合点3,当前已有[ 2 ]个线程已经到达,正在等候...
线程[ pool-1-thread-1 ]即将到达集合点3,当前已有[ 3 ]个线程已经到达,人到齐了,继续走啊!

 

posted @ 2017-08-18 11:44  半生戎马,共话桑麻、  阅读(111)  评论(0)    收藏  举报
levels of contents