CyclicBarrier 的字面意思是可循环使用(Cyclic)的屏障(Barrier)。它要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活。
一、应用举例
public class CyclicBarrierTest { private static CyclicBarrier cyclicBarrier; static class CyclicBarrierThread extends Thread { public void run() { System.out.println(Thread.currentThread().getName() + "到了"); try { cyclicBarrier.await(); } catch (Exception e) { e.printStackTrace(); } } } public static void main(String[] args) { cyclicBarrier = new CyclicBarrier(5, new Runnable() { @Override public void run() { System.out.println("人到齐了,开会吧...."); } }); for (int i = 0; i < 5; i++) { new CyclicBarrierThread().start(); } } }
二、类结构
public class CyclicBarrier { private static class Generation { // 内部类,当有parties个线程到达barrier,就会更新换代 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(); // 当有parties个线程到达barrier,就会更新换代 private int count; // 记录当前线程数量 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 await() throws InterruptedException, BrokenBarrierException {
try {
return dowait(false, 0L);
} catch (TimeoutException toe) {
throw new Error(toe); // cannot happen
}
}
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) { // 达到要求数量
boolean ranAction = false;
try {
final Runnable command = barrierCommand;
if (command != null)
command.run(); // 达到等待线程数量后执行barrierCommand
ranAction = true;
nextGeneration(); // 唤醒本代所有线程,生成新一代,重置count
return 0;
} finally {
if (!ranAction)
breakBarrier();
}
}
// 线程数量未达到要求数量,将线程挂起等待
for (;;) {
try {
if (!timed)
trip.await(); // 将线程加入condition队列挂起
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();
}
}
// 代失效,唤醒所有线程
private void breakBarrier() {
generation.broken = true;
count = parties;
trip.signalAll();
}
// 唤醒本代所有线程,生成新一代,重置count
private void nextGeneration() {
trip.signalAll();
count = parties;
generation = new Generation();
}
继续阅读与本文标签相同的文章
上一篇 :
全球机器人颜值大比拼,国内美女机器人佳佳才貌双全
下一篇 :
solr7环境要求及安装
-
PgSQL · 特性分析 · 浅析PostgreSQL 中的JIT
2026-05-19栏目: 教程
-
在AlibabaCloud上,如何使用AD FS进行 【角色SSO】 并完成在容器服务ACK集群中的身份验证
2026-05-19栏目: 教程
-
骚操作 !用 Python 偷偷抓取女朋友的行踪(女朋友在哪里)
2026-05-19栏目: 教程
-
受用一生的高效 PyCharm 使用技巧(五)
2026-05-19栏目: 教程
-
阿里云服务器从购买到入门使用流程 新手必看教程
2026-05-19栏目: 教程
