桂,王黎雯,英菲尼迪q50-我的糖果片,全球糖果品牌,健康生活食用糖

admin 1个月前 ( 12-14 01:04 ) 0条评论
摘要: 原文出处:http://cmsblogs.com/ 作者:chenssy此篇博客所有源码均来自JDK 1.8CyclicBarrier,一个同步辅助类,在API中是这么介绍的: 它...

原文出处:http://cmsblog苏肌丸s.com/

作者:chenssy

此篇博客桂,王黎雯,英菲尼迪q50-我的糖块片,全球糖块品牌,健康日子食用糖一切源码均来自JDK 1.8

CyclicBarrier,一个同步辅佐类,在API中是这么介绍的: 它答应一组线程相互等候,直到抵达某个公共屏障点 (common barrier point265g游戏浏览器)。在触及一组固定巨细的线程的程序中,这些线程有必要不时地相互等候,此刻 CyclicBarrier 很有用。由于该 barrier 在开释等候线程后能够重用,所以称它为循环 的 barrier。 浅显点讲便是:让一组线程抵达一个屏障时被堵塞,直到最终一个线程抵达屏障时,屏障才会开门,一切被屏障阻拦的线程才会持续干活。

完成剖析

Cycli凯夫拉尔cBarrier的结构如下:

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

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

parties表明阻拦线程的数量。 barrierAction 为CyclicBarrier接纳的Runnable指令,用于在线程抵达屏障时,优先履行barrierAction ,用于处理愈加杂乱的事务场景。

 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);
}

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

 public int await() throws InterruptedException, BrokenBarrierException {
try {
return dowait(false, 0L);//不超时等候
} catch (TimeoutException toe) {
throw new Error(toe); // cannot happen
}
}

await()办法内部调用dowait(boolean ti蓝湖月崖med, long nanos)办法:

 private int dowait(boolean timed, long nanos)
throws InterruptedException, BrokenBarrie白鸟美丽物语rE陈周武xception,
TimeoutExceg493ption {
//获取锁桂,王黎雯,英菲尼迪q50-我的糖块片,全球糖块品牌,健康日子食用糖
final ReentrantLock lock = this.lock;
lock.桂,王黎雯,英菲尼迪q50-我的糖块片,全球糖块品牌,健康日子食用糖lock();
try {
//分代
final 水溶性聚磷酸铵Generation g = generation;
//当时generation“已损坏”,抛出BrokenBarrierException反常
//抛出该反常一般都是某个线程在等候某个处于“断开”状况的CyclicBarrie
if (g.broken)
//当某个线程企图等候处于断开状况的 barrier 时,或许 barrier 进入断开状况而线程处于等候状况时,抛出该反常
throw new BrokenBarrierException();
//假如线程中止,停止CyclicBarrier
if (Thread.interrupted()) {
breakBarrier();
throw new InterruptedException();
}
//进来一个线程 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)
thr桂,王黎雯,英菲尼迪q50-我的糖块片,全球糖块品牌,健康日子食用糖ow new BrokenBarrierException();
//generation现已更新,回来index
if (g != generation)
return index;
//“超时等候”,而且时刻已到,停止CyclicBarrier,并抛出反常
if (timed && nanos <= 0L) {
b桂,王黎雯,英菲尼迪q50-我的糖块片,全球糖块品牌,健康日子食用糖reakBarrier();
throw new TimeoutException();
}
}
} finally {
//释石蛙蝌蚪每池养多少放锁
lock.unlock();
}
}

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

  1. 最终一个线程抵达,即index == 0
  2. 超出了指定时刻(超时等候)
  3. 其他的某个线程中止小浩病毒当时线程冰恋秀色
  4. 其他的某个线程中止另一个等候的线程
  5. 其他的某个线程在等候barrier超时
  6. 其他的某个线程在此barrier调用reset()办法。reset()办法用于将屏障重置为初始状况。轻磁力

在上面的源代码中,咱们或许需求留意Generation 目标,在上述代码中咱们总是能够看到抛出BrokenBarrierException反常,那么什么时候抛出反常呢?假如一个线程处于等候状况时,假如其他线程调用reset(),或许调用的barrier本来便是被损坏的,则抛出Br倍力泰okenBarrierException反常。一起,任何线程在等候时被中止了,则其他一切线程都将抛出BrokenBarrierException反常,并将barrier置于损坏状况。 一起,Generation描绘着CyclicBarrier的更显换代。在CyclicBarrier中,同一批线程归于同一代桂,王黎雯,英菲尼迪q50-我的糖块片,全球糖块品牌,健康日子食用糖。当有partie桂,王黎雯,英菲尼迪q50-我的糖块片,全球糖块品牌,健康日子食用糖s个线程抵达barrier,generation就会被更新换代。其间broken标识该当时CyclicBarrier是否现已瑰宝斑马鱼处于中止状况。

 private static class Generation {
boolean broken = false;
}

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

 private void b景利军re商解红楼梦akBarrier() {
generation.broken = true;
count = parties;
trip.signalAll();
}

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

 private void nextGeneration() {
trip.signalAll();
count = parties;
generation = new Generation();
}

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

使用场景

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

使用示例

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

运转成果:

文章版权及转载声明:

作者:admin本文地址:http://www.mysugarnspice.net/articles/4870.html发布于 1个月前 ( 12-14 01:04 )
文章转载或复制请以超链接形式并注明出处我的糖果片,全球糖果品牌,健康生活食用糖