CountDownLatch与CyclicBarrier

CountDownLatch与CyclicBarrier

java.util.concurrent.CountDownLatch extends Object

        一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。

        用给定的计数(利用构造函数)初始化CountDownLatch。由于调用了 countDown() 方法,所以在当前计数到达零之前,await 方法会一直受阻塞。等到CountDownLatch的计数为0之后,会释放所有等待的线程,await 的所有后续调用都将立即返回。这种现象只出现一次——计数无法被重置。如果需要重置计数,则考虑使用 CyclicBarrier

        CountDownLatch 是一个通用同步工具,它有很多用途。将计数 1 初始化的 CountDownLatch 用作一个简单的开/关锁存器,或入口:在通过调用 countDown() 的线程打开入口前,所有调用 await 的线程都一直在入口处等待。用 N 初始化的 CountDownLatch 可以使一个线程在 N 个线程完成某项操作之前一直等待,或者使其在某项操作完成 N 次之前一直等待。

         CountDownLatch 的一个有用特性是,它不要求调用 countDown 方法的线程等到计数到达零时才继续,它只是阻止任何线程继续通过一个 await,及await后面的代码,之后等到CountDownLatch计数为0时才会继续执行。

 

构造方法:

CountDownLatch(int count)     构造一个用给定计数(count)初始化的 CountDownLatch。

主要方法:

voidawait()
使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断
booleanawait(long timeout, TimeUnit unit)
使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断或超出了指定的等待时间。
voidcountDown()
递减锁存器的计数,如果计数到达零,则释放所有等待的线程。
longgetCount()
返回当前计数。
StringtoString()
返回标识此锁存器及其状态的字符串。

 

java.util.concurrent.CyclicBarrier extends Object

        一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点,在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。只有当所有参与进来的进程都到达屏障点,他们才能继续往下运行。

构造方法:

CyclicBarrier(int parties)
创建一个新的 CyclicBarrier,它将在给定数量(parties)的参与者(线程)处于等待状态时启动,但它不会在启动 barrier 时执行预定义的操作。参数
CyclicBarrier(int parties, Runnable barrierAction)
创建一个新的 CyclicBarrier,它将在给定数量(parties)的参与者(线程)处于等待状态时启动,并在启动 barrier 时执行给定的屏障操作,该操作由最后一个进入 barrier 的线程执行。也就是,当所有参与的线程都执行了await方法后,barrierAction中的run过程,以及所有线程await后面的代码才会执行。

主要方法:

intawait()
在所有参与者都已经在此 barrier 上调用 await 方法之前,将一直等待。
intawait(long timeout, TimeUnit unit)
在所有参与者都已经在此屏障上调用 await 方法之前将一直等待,或者超出了指定的等待时间。
intgetNumberWaiting()
返回当前在屏障处等待的参与者数目。
intgetParties()
返回要求启动此 barrier 的参与者数目。
booleanisBroken()
查询此屏障是否处于损坏状态。
voidreset()
将屏障重置为其初始状态。

 

实例1:每个参与的线程Runner在打印出“start runner:”后,必须等待所有的线程都打印出这句话。之后执行BarrierAction,以及继续执行await后面的代码。

public class Test {
	class Runner implements Runnable {
		int i;
		CyclicBarrier cb;
		Runner(int i, CyclicBarrier cb) {
			this.i = i;
			this.cb = cb;
		}
		@Override
		public void run() {
			System.out.println("start  runner: " + i);
			try {
				cb.await();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (BrokenBarrierException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println("end  runner: " + i);

		}

	}
	class BarrierAction implements Runnable {

		@Override
		public void run() {
			System.out.println("BarrierAction");
		}
	}
	public static void main(String[] args) {
		Test test = new Test();
		BarrierAction ba = test.new BarrierAction();
		CyclicBarrier cb = new CyclicBarrier(5, ba);
		ExecutorService es = Executors.newFixedThreadPool(5);
		for (int i = 0; i < 5; i++) {
			es.execute(test.new Runner(i, cb));
		}
	}
}

运行结果:

start  runner: 0
start  runner: 2
start  runner: 1
start  runner: 3
start  runner: 4
BarrierAction
end  runner: 4
end  runner: 2
end  runner: 3
end  runner: 0
end  runner: 1


 

实例2:CyclicBarrier和CountDownLatch综合应用

模拟赛跑,当所有Runner都准备好后才能统一起跑。每个人跑步的速度(speed)都不一样,要求当所有人跑完length长度之后,统计出最后一个到达终点的人的时间。

public class Runner implements Runnable {
	CyclicBarrier cb;
	String name; // 选手名称
	int length; // 跑步长度
	int speed; // 跑步速度
	CountDownLatch cd;

	public Runner(CountDownLatch cd, CyclicBarrier cb, String name, int speed,
			int length) {
		this.cb = cb;
		this.name = name;
		this.speed = speed;
		this.length = length;
		this.cd = cd;
	}

	@Override
	public void run() {
		System.out.println(name + "准备好了!");
		try {
			cb.await(); // 自己准备好之后等待其他人也准备就绪
		} catch (InterruptedException | BrokenBarrierException e) {
			e.printStackTrace();
		}
		int kk = 0;
		while (length > 0) {
			length -= speed;
			kk += speed;
			System.out.println(name + "跑了" + kk);
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		cd.countDown();
		System.out.println(name + "到达终点");
	}
}

 

public class BarrierAction implements Runnable {
	public void run() {
		System.out.println("所有选手起跑了!");
	}
}


 

public class Game {
	public static void main(String[] args) throws InterruptedException {
		ExecutorService es = Executors.newFixedThreadPool(5);
		CyclicBarrier cb = new CyclicBarrier(5);
		CountDownLatch cd = new CountDownLatch(5);
		Long start = System.currentTimeMillis();
		for (int i = 0; i < 5; i++) {
			es.execute(new Runner(cd, cb, "runner" + i, i + 1, 10));
		}
		cd.await();
		// 当所有人都到达终点后,统计处最后一个到达终点的用时。
		System.out.println("全部到达终点,用时: " + (System.currentTimeMillis() - start)
				* 1.0 / 1000);
		es.shutdown();
	}
}


运行结果:

runner0准备好了!
runner1准备好了!
runner2准备好了!
runner3准备好了!
runner4准备好了!
所有选手起跑了!
runner4跑了5
runner0跑了1
runner1跑了2
runner2跑了3
runner3跑了4
runner3跑了8
runner2跑了6
runner4跑了10
runner1跑了4
runner0跑了2
runner1跑了6
runner4到达终点
runner2跑了9
runner3跑了12
runner0跑了3
runner0跑了4
runner3到达终点
runner1跑了8
runner2跑了12
runner0跑了5
runner1跑了10
runner2到达终点
runner0跑了6
runner1到达终点
runner0跑了7
runner0跑了8
runner0跑了9
runner0跑了10
runner0到达终点
全部到达终点,用时: 5.002


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值