循环计数器/循环栅栏/循环屏障 CyclicBarrier
CyclicBarrier
和 CountDownLatch 有点类似,主要区别是 CyclicBarrier 可以重用,常用方法如下:
CyclicBarrier barrier = new CyclicBarrier(3); // 表示条件为:要有 3 个线程达到屏障(未指定屏障动作)
barrier.await(); // 如果没有 3 个线程到达屏障,当前线程就阻塞,直到有 3 个线程达到才恢复
// 指定屏障动作
CyclicBarrier barrier = new CyclicBarrier(3, new Runnable() {
@Override
public void run() {
System.out.println("All parties have arrived at the barrier, let's continue.");
}
});
await() 底层是让 state - 1,达到栅栏的线程数量足够时,state 会重置,这样来体现可重用的。CountDown 不会重置 state
如果要使用线程池,线程池数量要和 CyclicBarrier 计数器一致
用法示例1
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.TimeoutException;
public class CyclicBarrierExample {
public static void main(String[] args) {
// 创建一个 CyclicBarrier,设定需要3个线程到达屏障
CyclicBarrier barrier = new CyclicBarrier(3, new Runnable() {
@Override
public void run() {
// 当 3 个线程到达屏障,执行屏障动作
System.out.println("All threads have reached the barrier, resuming execution.");
}
});
// 启动3个线程,它们都会到达屏障
for (int i = 0; i < 3; i++) {
new Thread(new Worker(barrier)).start();
}
}
}
class Worker implements Runnable {
private CyclicBarrier barrier;
public Worker(CyclicBarrier barrier) {
this.barrier = barrier;
}
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " is waiting at the barrier.");
barrier.await(); // 当前线程挂起了,下面这行不会打印,直到 3 个线程达到屏障,当前线程恢复运行
System.out.println(Thread.currentThread().getName() + " has passed the barrier.");
} catch (InterruptedException | BrokenBarrierException e) {
Thread.currentThread().interrupt();
}
}
}
用法示例2
执行两次,第二次执行的时候没有重新创建 CyclicBarrier,体现可重用
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.TimeoutException;
public class CyclicBarrierReusableExample {
public static void main(String[] args) {
final int numberOfThreads = 3;
final CyclicBarrier barrier = new CyclicBarrier(numberOfThreads, new Runnable() {
@Override
public void run() {
System.out.println("Barrier reached! All threads completed the phase.");
}
});
Runnable task = () -> {
try {
System.out.println(Thread.currentThread().getName() + " is performing task.");
Thread.sleep((long) (Math.random() * 1000));
System.out.println(Thread.currentThread().getName() + " finished task and waiting at the barrier.");
barrier.await();
// Phase complete, proceed to the next phase
System.out.println(Thread.currentThread().getName() + " moving to the next phase.");
} catch (InterruptedException | BrokenBarrierException e) {
Thread.currentThread().interrupt();
}
};
// Launch threads for phase 1
for (int i = 0; i < numberOfThreads; i++) {
new Thread(task).start();
}
// Wait for all threads to complete phase 1 and then start phase 2
try {
Thread.sleep(2000); // Simulate some delay between phases
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("Starting next phase...");
// Launch threads for phase 2, using the same barrier
for (int i = 0; i < numberOfThreads; i++) {
new Thread(task).start();
}
}
}
改成 CountDown,因为 CountDown 的计数器不会重置,所以要创建多个 CountDown
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.BrokenBarrierException;
public class CountDownLatchExample {
public static void main(String[] args) {
final int numberOfThreads = 3;
// Define a task
Runnable task = new Runnable() {
private CountDownLatch latch;
public Runnable withLatch(CountDownLatch latch) {
this.latch = latch;
return this;
}
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " is performing task.");
// Simulate some work
Thread.sleep((long) (Math.random() * 1000));
System.out.println(Thread.currentThread().getName() + " finished task and waiting at the latch.");
latch.await(); // Wait until the latch count reaches zero
// Phase complete, proceed to the next phase
System.out.println(Thread.currentThread().getName() + " moving to the next phase.");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
};
// Method to start threads with a CountDownLatch
void startPhase(int numberOfThreads) {
CountDownLatch latch = new CountDownLatch(numberOfThreads);
// Start threads
for (int i = 0; i < numberOfThreads; i++) {
new Thread(task.withLatch(latch)).start();
}
// Release the latch after all threads have started
new Thread(() -> {
try {
Thread.sleep(2000); // Simulate some delay before releasing the latch
System.out.println("Releasing the latch!");
latch.countDown(); // Count down the latch to zero
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
}
// Start phase 1
startPhase(numberOfThreads);
// Wait for some time before starting the next phase
try {
Thread.sleep(3000); // Simulate some delay between phases
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("Starting next phase...");
// Start phase 2
startPhase(numberOfThreads);
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具