在Java并发编程中,线程间的协作与通信是实现复杂并发逻辑的关键。Phaser
, CyclicBarrier
, 和 Semaphore
是Java并发包提供的强大工具,它们分别适用于不同的同步需求。本文将深入浅出地介绍这三个组件的使用场景、常见问题及避免策略,并附上代码示例。
1. Phaser - 阶段性任务协调器
介绍
Phaser
是一个灵活的同步屏障,支持动态注册和取消注册参与者,适用于有多个阶段的任务执行流程。
常见问题与避免策略
- 问题:过度依赖动态注册,导致阶段结束条件难以预测。
- 避免:明确每个阶段的预期参与者数量,适时使用
arriveAndDeregister
方法。
示例
代码语言:javascript复制import java.util.concurrent.Phaser;
public class PhaserDemo {
public static void main(String[] args) {
Phaser phaser = new Phaser(1); // 初始参与者为1(主线程)
for (int i = 0; i < 3; i ) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() " arrived.");
phaser.arriveAndAwaitAdvance(); // 到达并等待所有到达
System.out.println(Thread.currentThread().getName() " continuing.");
}, "Thread-" (i 1)).start();
}
phaser.arriveAndDeregister(); // 主线程到达并注销
}
}
2. CyclicBarrier - 循环屏障
介绍
CyclicBarrier
允许一组线程相互等待,直到达到某个屏障点后一起继续执行。它支持重置和重复使用,适用于循环执行的任务。
常见问题与避免策略
- 问题:忘记处理
BrokenBarrierException
,导致程序意外终止。 - 避免:在
run()
方法中捕获并适当处理此异常。
示例
代码语言:javascript复制import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierDemo {
public static void main(String[] args) {
int parties = 3;
CyclicBarrier barrier = new CyclicBarrier(parties, () -> System.out.println("All threads reached the barrier."));
for (int i = 0; i < parties; i ) {
new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName() " is waiting on barrier.");
barrier.await(); // 等待所有线程到达
System.out.println(Thread.currentThread().getName() " continued.");
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}, "Thread-" (i 1)).start();
}
}
}
3. Semaphore - 信号量
介绍
Semaphore
是一种计数信号量,用于控制同时访问特定资源的线程数量,常用于限流和资源池管理。
常见问题与避免策略
- 问题:未正确释放信号量,导致资源泄露。
- 避免:确保
acquire
和release
成对出现,即使在异常情况下也要释放。
示例
代码语言:javascript复制import java.util.concurrent.Semaphore;
public class SemaphoreDemo {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(2); // 允许两个线程同时访问
for (int i = 0; i < 5; i ) {
new Thread(() -> {
try {
semaphore.acquire(); // 获取许可
System.out.println(Thread.currentThread().getName() " entered the critical section.");
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() " leaving the critical section.");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
semaphore.release(); // 释放许可
}
}, "Thread-" (i 1)).start();
}
}
}
总结而言,Phaser
, CyclicBarrier
, 和 Semaphore
分别提供了不同维度的线程间通信和同步机制。理解它们的特性和正确使用,是实现高效并发程序的关键。在实际应用中,应根据具体场景选择合适的工具,并注意异常处理和资源管理,以避免常见的并发陷阱。