1:CyclicBarrier 基本知识
1:字面意思是可循环使用(Cyclic)的屏障(Barrier)。让一组线程全部到达屏障时,屏障才会开门,被屏障拦截的线程才会继续运行。先到达的线程处于阻塞状态。
2:使用场景:可以用于多线程计算数据,最后合并结果的场景。
3:CountDownLatch的计数器只能使用一次,而CyclicBarrier的计数器可以使用reset()方法重置。
4:一般和固定数目线程池配合使用,线程数目二者最好定义相同
2:构造方法
默认构造方法 :传入拦截的线程总数
public CyclicBarrier(int parties) {
// 调用重载方法,也就是另外的构造方法
this(parties, null);
}
进入重载方法:另一个构造方法
public CyclicBarrier(int parties, Runnable barrierAction) {
// 拦截的线程数目不能 <=0,否则会抛出异常
if (parties <= 0) throw new IllegalArgumentException();
// 传入一个任务,当线程到达屏障时,优先执行这个任务
this.parties = parties;
this.count = parties;
this.barrierCommand = barrierAction;
}
3:阻塞方法 await
需要等待的线程需要调用 await() 方法
public int await() throws InterruptedException, BrokenBarrierException {
try {
// 进入 dowait(false, 0L) 方法
return dowait(false, 0L);
} catch (TimeoutException toe) {
throw new Error(toe); // cannot happen
}
}
进入 dowait(false, 0L) 方法
private int dowait(boolean timed, long nanos)
throws InterruptedException, BrokenBarrierException,
TimeoutException {
// 可以看出内部有一个 ReentrantLock 锁
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();
}
// 屏障数目 减 1 ,判断 减 1 后是否等于 0
int index = --count;
if (index == 0) {
boolean ranAction = false;
try {
// 如果构造器传进来的优先任务不为 null, 优先执行
final Runnable command = barrierCommand;
if (command != null)
command.run();
ranAction = true;
// 进入 nextGeneration() 方法
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();
}
}
进入 nextGeneration() 方法
private void nextGeneration() {
// 进入 Condition.signalAll() 方法
trip.signalAll();
count = parties;
generation = new Generation();
}
进入 Condition.signalAll() 方法
public final void signalAll() {
// 判断拥有 ReentrantLock 锁的线程是不是当前线程,不是的话抛出异常
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
// Conditinon 中的第一个节点,如果不为空,进入 doSignalAll(first) 方法
Node first = firstWaiter;
if (first != null)
doSignalAll(first);
}
进入 doSignalAll(first) 方法
private void doSignalAll(Node first) {
// 将 Conition 的节点删除移动到 AQS 的等待队列中,只不过所有节点的顺序往后推一位,头节点是亚元节点
lastWaiter = firstWaiter = null;
do {
Node next = first.nextWaiter;
first.nextWaiter = null;
transferForSignal(first);
first = next;
} while (first != null);
}
回到 nextGeneration() 方法
private void nextGeneration() {
// Condition.signalAll() :将 Condition 节点删除移动到 AQS 等待队列
trip.signalAll();
count = parties;
// 创建一个新的实例,屏障的每次新的使用都会创建一个实例
generation = new Generation();
}
回到 dowait(false, 0L) 方法
private int dowait(boolean timed, long nanos)
throws InterruptedException, BrokenBarrierException,
TimeoutException {
// 可以看出内部有一个 ReentrantLock 锁
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();
}
// 屏障数目 减 1 ,判断 减 1 后是否等于 0
int index = --count;
if (index == 0) {
boolean ranAction = false;
try {
// 如果构造器传进来的优先任务不为 null, 优先执行
final Runnable command = barrierCommand;
if (command != null)
command.run();
ranAction = true;
// 进入 nextGeneration() 方法
nextGeneration();
return 0;
} finally {
// ranAction 等于 true,不满足条件
if (!ranAction)
breakBarrier();
}
}
// 屏障数目 减 1 大于 0,如果进入 for 循环
for (;;) {
try {
// 如果没有传等待时间,那么进入 Condition.await() 方法;否则进入超时的Condition.awaitNanos()方法
// 生成一个新的节点,添加到 Conditon 双向链表的尾端,释放节点上持有的同步锁,并阻塞住
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 {
// 最后 ReentrantLock 进行解锁
lock.unlock();
}
}