首页 欧洲联赛正文

色爷爷,「死磕Java并发」—–J.U.C之并发东西类:CyclicBarrier,唐河天气预报

原文出处:http://cmsblogs.com/

作者:chenssy

此篇博客一切源码均来自JDK 1.8

CyclicBarrier,一个同步辅佐类,在API中是这么介绍的: 它答应一组线程相互等候,直到抵达某个公共屏障点 (common barrier point)。在触及一组固定巨细的线程的程序中,这些线程有必要不时地相互等候,此刻 CyclicBarrier 很有用。由于该 barrier 在开释等候线程后能够重用,所以称它为循环 的 barrier。 浅显点讲便是:让一组线程抵达一个屏障时被堵塞,直到最终一个线色爷爷,「死磕Java并发」—–J.U.C之并发东西类:CyclicBarrier,唐河天气预报程抵达屏障时,屏障才会开门,一切被屏障阻拦的线程才会持续干活。

完成剖析

CyclicBarrier的结构如下:

经过上图咱们能够看到CyclicBarrier的内部是运用重入锁ReentrantLock和Condition。它有两个结构函数:

  • C纪忠哲yclicBarrier(int parties):创立一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等候状况时发动,但它不会在发动 barrier 时履行预界说的操作。
  • CyclicBarrier(int parties, Runnable barrierAction) :创立一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等候状况时发动,并在发动 barrier 时履行给定的屏障操作,该操作由最终一个进入 barrier 的线程履行。

parties表明阻拦线程的数量。 barrierAction 为CyclicBarrier接纳色爷爷,「死磕Java并发」—–J.U.C之并发东西类:CyclicBarrier,唐河天气预报的Runnable指令,用于在线程抵达屏障时,优先履行barrierAction ,用于处理愈加杂乱的事务场景。

 public CyclicBarrier(int parties, Runnab傅国慧le barrierAction) {
if (parties <= 0) throw new IllegalArgumentException();
this.parties = parties;
this.count = parties;
this.barrierCommand = barrierAction;
}
public CyclicBarrier(int parties) {
this(parties, null);
}

在CyclicBarrier中最重要的办法莫过于await()办法,在一切参与者都现已在此 barrier 上调用 await 办法之前,将一向等候。如下:

 public int await() throws Inte日本午夜rr鹿兆麟uptedException, BrokenBarrierException {
try {
return dowait(false, 0L);//不超时等候
} catch (TimeoutException toe) {
throw new Error(toe); // cannot happen
}
}

await()办法内部调用dowait(boolean timed, long nanos)办法:

 private int dowait(boolean timed, long nanos)
throws InterruptedException, BrokenBarrierException,
TimeoutException {
//获取锁
final ReentrantLock lock = this.lock;
lock.lock();
try {
//分代
final Generation g = generation;
//当时generation“已损坏”,抛出BrokenBarrierException反常
//抛出该反常一般都是某个线程在等候某个处于“断开”状况的CyclicBarrie
if (g.broken)
//当某个线程企图等候处于断开状况的 barrier 时,或许 barrier 进入断开状况而线程处于等候状况时,抛出该反常
throw new BrokenBarrierExcepti步氏神族on();
//假如线程中止,停止CyclicBarrier
if (T小趣块链hread.interrupted()) {
breakBarrier();
throw new Interrupt男肉畜edEx色爷爷,「死磕Java并发」—–J.U.C之并发东西类:CyclicBarrier,唐河天气预报c色爷爷,「死磕Java并发」—–J.U.C之并发东西类:CyclicBarrier,唐河天气预报eption();
}
//进来一个线程 count - 1
int index = --count;
//count == 0 表明一切线程均已到位,触发Runnable使命
if (index == 0) { // tripped
boolean ranAction = false;
try {
final Runnable command = barrierCommand;
//触发使命
if (command != null)
command.run();
ranAction = true;
//唤醒一切等候线程,并更新generation
nextGeneration();
return 0;
} finally {
if (!ranAction)
breakBarrier();
}
}
for (;;) {
try {
//假如不是超时等候,则调用Condition.await()办法等候
if (!timed)
trip.await();
else if (nanos > 0L)
//超时等候,调用Condition.awaitNanos()办法等候
nanos = trip.awaitNanos(nanos);
} catch (InterruptedException ie) {
if (g == generation && ! g.broken) {
breakBarrier();
throw ie;
} else {
// We're about to finish waiting even if we had not
// been interrupted, so this interrupt is deemed to
// "belong" to subsequent execution.
Thread.currentThread().interrupt();
}
}
if (g.broken)
throw new Broke初中女生图片nBarrierException();栾英伟
//generation现已更新,色爷爷,「死磕Java并发」—–J.U.C之并发东西类:CyclicBarrier,唐河天气预报回来index
if (g != generation)
return index;
//“超时等候”,而且时刻已到,停止CyclicBarrier,并抛出反常
if (timed && nanos <= 0L) {
bssldreakBarrier();
throw new TimeoutException();
}
}
} finally {
//开释锁
lock.unlock();
}
}

其实await()的处理逻辑仍是比较简单的:假如该线程不是抵达的最终一个线程,则他会一向处于等候状况,除非发作以下状况:

  1. 最终一个线程抵达,即index == 0
  2. 超出了指定时刻(超时等候出彩我国人龙拳小子)
  3. 其他的某个线程中止当时线程
  4. 其他的某个线程中止另一个色爷爷,「死磕Java并发」—–J.U.C之并发东西类:CyclicBarrier,唐河天气预报等候的线程
  5. 其他的某个线程在等候barrier超时
  6. 其他的某个线程在此barrier调用re色爷爷,「死磕Java并发」—–J.U.C之并发东西类:CyclicBarrier,唐河天气预报set()办法。教你学悉数海南话reset()办法用于将屏障重置为初始状况。

在上面的源代码中,咱们或许需求留意Generation 目标,在上述代码中咱们总是可聚合道德以看到抛出BrokenBarrierException反常,那么什么时候抛出反常呢?假如一个线程处于等候状况时,假如其他线程调用reset(),或许调用的barrier本来便是被损坏的,则抛出BrokenBarrierException反常。虎扑路人王军哥一起,任何线程在等候时被中止了,则其他一切线程都将抛出BrokenBarrierException反常,并将barrier置于损坏状况。 一起,G重生之黄埔军魂eneration描绘着CyclicBarrier的更显换代。在CyclicBarrier中,同一批线程归于同一代。当有parties个线程抵达barrier,generation就会被更新换代。其间broken标识该当时CyclicBarrier是否现已处于中止状况。

 private static class Generation {
boolean broken = false;
}

默许barrier是没有损坏的。 当barrier损坏了或许有一个线程中止了,则经过breakBarrier()来停止一切的线程:

 private void breakBarrier() {
generation.broken = true;
count = parties;
trip.signalAll();
}

在breakBarrier()中除了将broken设置为true,还会调用signalAll将在CyclicBarrier处于等候状况的线程悉数唤醒。 当一切线程都现已抵达barrier处(index == 0),则会经过nextGeneration()进行更新换地操作,在这个过程中,做了三件事:唤醒一切线程,重置count,generation。

 private void n任家蓉extGeneration() {
trip.signalAll();
count = parties;
generation = new Generation();
}

CyclicBarrier一起也供给了await(long timeout, TimeUnit unit) 办法来做超时操控,内部仍是经过调用doawait()完成的。

使用场景

CyclicBarrier试用与多线程成果兼并的操作,同性恋相片用于多线程核算数据,最终兼并核算成果的性感背影使用场景。比方咱们需求核算多个Excel中的数据,然后比及一个总成果。咱们能够经过多线程处理每一个Excel,履行完成后得到相应的成果,最终经过barrierAction来核算这些黑客杜天禹线程的核算成果,得到一切Excel的总和。

使用示例

比方咱们开会只要等一切的人到齐了才会开会,如下:

运转成果:

版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

欧珀莱,景业名邦:微支点下的救命稻草,徐小明新浪博客

  • 头发颜色,“世界袜都”变革记:数字化添传统企业转型之翼,virtualbox

  • 维多利亚的秘密,成都区域废铜商场报价(11月21日),新中式装修效果图

  • 北京市人力资源和社会保障局,部分债权人要求法院驳回贾跃亭破产重组请求 或转为破产清算,小孩发烧

  • 寒假手抄报,福星股份:连续4日融资净偿还累计338.84万元(11-20),分

  • 4399生死狙击,东阿阿胶:融资净买入61.11万元,融资余额7.36亿元(11-20),考研的条件

  • 龙珠z,【净网2019】上海公安机关深入推进“APP违法采集个人信息”集中整治工作,彩宝贝

  • 蕲,分众传媒:接连3日融资净买入累计3609.43万元(11-20),张国强