概述
阅读需知
- jdk版本:1.8
- 使用/* */注释的方法会做深入分析
正文
CyclicBarrier(循环屏障),一种同步辅助工具,允许一组线程全部等待彼此到达公共障碍点,它可以在等待线程释放后循环重新使用,我们首先来看一下它的构造方法:
public CyclicBarrier(int parties) {
this(parties, null);
}
/**
* @param parties 在屏障被触发之前必须调用await方法的线程数
* @param barrierAction 屏障触发时执行的命令,如果没有操作则执行 null
*/
public CyclicBarrier(int parties, Runnable barrierAction) {
if (parties <= 0) throw new IllegalArgumentException();
this.parties = parties;
this.count = parties;
this.barrierCommand = barrierAction;
}
我们可以调用其 await 方法使当前线程等待直到 parties 数量的线程在此屏障上调用了 await 方法,我们来看 await 方法的实现:
CyclicBarrier:
public int await() throws InterruptedException, BrokenBarrierException {
try {
/* 无参 await 方法传入的 timeout 为0,我们可以调用有参 await 传入 timeout 超时时间 */
return dowait(false, 0L);
} catch (TimeoutException toe) {
throw new Error(toe);
}
}
CyclicBarrier:
private int dowait(boolean timed, long nanos)
throws InterruptedException, BrokenBarrierException,
TimeoutException {
final ReentrantLock lock = this.lock;
lock.lock();
try {
// 屏障的每次使用都表示为 Generation 实例,每当屏障被触发或重置时,Generation 都会改变
final Generation g = generation;
if (g.broken)
throw new BrokenBarrierException();
if (Thread.interrupted()) {
// 如果当前线程已经中断,将当前屏障 Generation 设置为已损坏并唤醒所有线程
breakBarrier();
throw new InterruptedException();
}
// 每次调用,递减 count
int index = --count;
// 递减为0触发屏障
if (index == 0) {
boolean ranAction = false;
try {
// 如果设置了 barrierCommand,则在触发屏障时运行 command
final Runnable command = barrierCommand;
if (command != null)
command.run();
ranAction = true;
// 屏障触发时更新状态并唤醒所有线程
nextGeneration();
return 0;
} finally {
if (!ranAction)
// 没有成功的运行 command,标记屏障为已损坏
breakBarrier();
}
}
// 循环直到屏障触发、损坏、中断或者超时
for (;;) {
try {
if (!timed)
// 如果没有使用超时时间,直接调用 condition 的 await 方法阻塞等待
trip.await();
else if (nanos > 0L)
// 如果指定了超时时间,则调用 condition 可以指定超时时间的 awaitNanos 方法阻塞等待
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();
// 如果已经生成了新的 Generation 实例,则说明已经触发屏障
if (g != generation)
return index;
// 超时判断
if (timed && nanos <= 0L) {
breakBarrier();
throw new TimeoutException();
}
}
} finally {
lock.unlock();
}
}
这个方法就是整个 CyclicBarrier 的核心代码了,整体基于 ReentrantLock 和 ReentrantLock.Condition 实现,到这里,CyclicBarrier 的源码分析就完成了。
最后
以上就是结实星星为你收集整理的CyclicBarrier 源码解析的全部内容,希望文章能够帮你解决CyclicBarrier 源码解析所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复