cyclicbarrier java_JAVA CyclicBarrier 通俗理解

/*

* 循环屏障

* 由分支线程主导任务执行

* 例:五人相约吃饭(1、2、3、4、5,5个线程,最后到的负责叫服务员点餐),因为各走各的(步行的、开车的、坐地铁的等),所以到达饭店有先有后

* 第一次

* 假设2先到,发现自己不是最后一个人,所以等待,

* 然后3也到了,也发现自己不是最后一个,所以等待,

* 这时4在来的路上突然临时有事,去不了了,就通知其它人,下次再聚

* 其他人收到通知到了的就回家,没到的也不会再去,也会回家

* 第二次

* 哥五个商量好了,第二天再次聚餐

* 这次,假设1、3、4都已经到饭店了在等2和5

* 在等的过程中,4突然接到电话有事,不能吃饭了,则通知其它人,下次再聚

* 这时1和3就会被告知别等了不能吃了回家吧,2和5没来在路上也会收到通知直接回家

* 第三次吃饭

* 这次假设1、4、5都到了在等待,4来的时候就告诉了,我今天还有事哈就能等半个小时,

* 半个小时人没到齐我还得走

* 结果时间到了,3来了2还没到,

* 完又吃不成了,叫醒等睡着的1、3、5通知2也不用来了都回家吧。

* 第四次吃饭

* 这次假设1、2、3、5都分别到达了吃饭的地,谁今天都没事,都等最后一个到了就吃饭

* 4这时候到了,发现自己最后一个到的,于是就叫服务员点餐吃饭

* 吃饭吃的挺好,也没出别的事

* 吃饭完哥几个相约过几天接着约哈。

*/

public class CyclicBarrier {

/*

* 每次饭局破坏情况

*/

private static class Generation {

//false饭局未被破坏,true饭局遭到破坏

boolean broken = false;

}

/*

* 饭店大门一次只能进一个人

* 进去的人在里面落座了或者出来了才能进下一个

*/

private final ReentrantLock lock = new ReentrantLock();

/*

* 饭店休息室,可大可小的休息室,反正几个人都能容下,先到的都在这等着

*/

private final Condition trip = lock.newCondition();

/*

* 吃饭人数

*/

private final int parties;

/*

* 最后一个到场的人要负责的事

*/

private final Runnable barrierCommand;

/*

* 每次饭局破坏情况

*/

private Generation generation = new Generation();

/*

* 统计未到场人数

*/

private int count;

/*

* 吃好了,相约下次再聚

*/

private void nextGeneration() {

trip.signalAll();

count = parties;

generation = new Generation();

}

/*

* 饭局遭受破坏,到场的人都散了吧

* 未到场人数设置为全员

*/

private void breakBarrier() {

generation.broken = true;

count = parties;

trip.signalAll();

}

/*

* 一个一个进饭店

* 先到的先到休息室等人,

* 最后一个到的叫服务员点餐,同时通知所有在休息室的人到包间吃饭

* 人齐吃饭,吃完吃好相约下次再聚

* 人在到齐的过程中,有一人有事未到则取消饭局

* 人在到齐的过程中,到的人中有一人有事离开,饭局取消

* 人在到齐的过程中,到的人中,有一人等时间长了,不等离开了,饭局取消

* 在吃饭的过程中没吃好,谈合同没谈好,饭局取消

*/

private int dowait(boolean timed, long nanos)

throws InterruptedException, BrokenBarrierException,

TimeoutException {

final ReentrantLock lock = this.lock;

lock.lock();

try {

final Generation g = generation;

if (g.broken)

throw new BrokenBarrierException();

if (Thread.interrupted()) {

breakBarrier();

throw new InterruptedException();

}

int index = --count;

//最后一个到场的,叫服务员点餐,通知所有等待的人吃饭

if (index == 0) { // tripped

boolean ranAction = false;

try {

final Runnable command = barrierCommand;

if (command != null)

command.run();

ranAction = true;

nextGeneration();

return 0;

} finally {

if (!ranAction)

breakBarrier();

}

}

// 先到场的进去等

// 临时有事的,等不及的就走,

//走的时候通知其它等待的人也走

for (;;) {

try {

if (!timed)

trip.await();

else if (nanos > 0L)

nanos = trip.awaitNanos(nanos);

} catch (InterruptedException ie) {

if (g == generation && ! g.broken) {

breakBarrier();

throw ie;

} else {

Thread.currentThread().interrupt();

}

}

if (g.broken)

throw new BrokenBarrierException();

if (g != generation)

return index;

if (timed && nanos <= 0L) {

breakBarrier();

throw new TimeoutException();

}

}

} finally {

lock.unlock();

}

}

/*

* 形成吃饭这件事的共识,并约定几个人吃,最后到的人负责通知服务员点餐

*/

public CyclicBarrier(int parties, Runnable barrierAction) {

if (parties <= 0) throw new IllegalArgumentException();

this.parties = parties;

this.count = parties;

this.barrierCommand = barrierAction;

}

/*

* 形成吃饭这件事的共识,并约定几个人吃,自助餐,不用叫服务员点餐

*/

public CyclicBarrier(int parties) {

this(parties, null);

}

/*

* 获取吃饭人数

*/

public int getParties() {

return parties;

}

/*

* 吃饭的人没有其它预约,所以不设置到场等待时间

*/

public int await() throws InterruptedException, BrokenBarrierException {

try {

return dowait(false, 0L);

} catch (TimeoutException toe) {

throw new Error(toe); // cannot happen

}

}

/*

* 吃饭的人有其它预约,到时间就得走

*/

public int await(long timeout, TimeUnit unit)

throws InterruptedException,

BrokenBarrierException,

TimeoutException {

return dowait(true, unit.toNanos(timeout));

}

/*

* 获取饭局是否被破坏

*/

public boolean isBroken() {

final ReentrantLock lock = this.lock;

lock.lock();

try {

return generation.broken;

} finally {

lock.unlock();

}

}

/*

* 重置饭局

*/

public void reset() {

final ReentrantLock lock = this.lock;

lock.lock();

try {

breakBarrier(); // break the current generation

nextGeneration(); // start a new generation

} finally {

lock.unlock();

}

}

/*

* 获取到场人数

*/

public int getNumberWaiting() {

final ReentrantLock lock = this.lock;

lock.lock();

try {

return parties - count;

} finally {

lock.unlock();

}

}

}

CyclicBarrier与CountDownLatch比较

CyclicBarrier是由分线程主导,分线程最后一个去执行一项任务,执行完后唤醒其它线程继续执行。不存在另外一个不同类的线程等待。

CountDownLatch是有一个线程在等待其它线程执行,其它线程中的最后一个执行完去唤醒这个等待的线程继续执行。存在一个不同类的线程等待。

CountDownLatch举例:下班的班车司机等全员到齐出发

司机是一个线程他在等全员到齐,所有员工是其它线程,最后一个上车的员工通知司机我是最后一个,人齐了可以出发了。司机收到讯息后启动班车出发。

以上如有不足望或错误望指正。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值