目录
一、并发工具类的演进背景与核心价值
1. 传统同步机制的局限性
- synchronized:仅支持简单互斥,缺乏灵活的线程协作能力
- wait/notify:需要手动管理等待队列,易引发虚假唤醒
- Lock:需手动释放锁,增加代码复杂度
二、核心工具类深度解析
1. CountDownLatch:线程等待器
1.1 核心机制
- 计数器模式:通过
countDown()
递减计数器,await()
阻塞等待归零 - 不可重用性:计数器归零后无法重置
- 超时机制:支持
await(long timeout, TimeUnit unit)
1.2 典型应用场景
// 多线程任务完成通知
ExecutorService executor = Executors.newFixedThreadPool(3);
CountDownLatch latch = new CountDownLatch(3);
for (int i = 0; i < 3; i++) {
executor.submit(() -> {
try {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + " 完成任务");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
latch.countDown();
}
});
}
latch.await();
System.out.println("所有任务已完成");
executor.shutdown();
2. CyclicBarrier:循环屏障
2.1 核心特性
- 可重用性:通过
reset()
方法重置屏障- 屏障动作:可指定一个
Runnable
在屏障触发时执行- parties 参数:需等待的线程数量
2.3 示例代码
// 多线程计算协作
CyclicBarrier barrier = new CyclicBarrier(3, () -> {
System.out.println("所有线程完成阶段性任务");
});
ExecutorService executor = Executors.newFixedThreadPool(3);
for (int i = 0; i < 3; i++) {
executor.submit(() -> {
try {
Thread.sleep((long) (Math.random() * 2000));
System.out.println(Thread.currentThread().getName() + " 到达屏障");
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
});
}
executor.shutdown();
3. Phaser:多功能相位器
3.1 核心功能
- 动态线程注册:支持
register()
和bulkRegister(int)
- 分阶段同步:通过
arriveAndAwaitAdvance()
进入下一阶段- 终止检测:通过
isTerminated()
判断是否所有线程完成
3.2 与 CyclicBarrier 的对比
特性 | CyclicBarrier | Phaser |
---|---|---|
线程数量 | 固定 parties | 动态可调整 |
阶段数量 | 单次屏障 | 多阶段 |
终止机制 | 需手动 reset | 自动终止或强制终止 |
三、高级工具类详解
1. Exchanger:线程间数据交换
1.1 工作原理
- 交换对:两个线程调用
exchange(V x)
时交换数据 - 超时机制:支持
exchange(V x, long timeout, TimeUnit unit)
- 适用场景:生产者 - 消费者模式中的数据交换
1.2 代码示例
// 数据处理流水线
Exchanger<List<String>> exchanger = new Exchanger<>();
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.submit(() -> {
List<String> data = Arrays.asList("A", "B", "C");
System.out.println("生产者提交数据: " + data);
try {
List<String> processed = exchanger.exchange(data);
System.out.println("生产者接收处理后的数据: " + processed);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
executor.submit(() -> {
try {
List<String> data = exchanger.exchange(null);
List<String> processed = data.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println("消费者处理数据: " + processed);
exchanger.exchange(processed);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
executor.shutdown();
2. Semaphore:信号量
2.1 核心功能
- 资源控制:通过
acquire()
获取许可,release()
释放 - 公平性支持:构造函数可指定公平策略
- 批量获取:支持
acquire(int permits)
2.2 典型应用
// 数据库连接池控制
Semaphore semaphore = new Semaphore(5);
for (int i = 0; i < 10; i++) {
new Thread(() -> {
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + " 获取连接");
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName() + " 释放连接");
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
四、工具类选择与性能优化
1. 工具类选择矩阵
场景类型 | 推荐工具类 | 替代方案 |
---|---|---|
任务等待 | CountDownLatch | Future.get() |
循环同步 | CyclicBarrier | Phaser |
多阶段同步 | Phaser | 嵌套 CountDownLatch |
数据交换 | Exchanger | BlockingQueue |
资源控制 | Semaphore | synchronized 计数器 |
2. 性能优化策略
- 减少线程阻塞:优先使用带超时的等待方法
- 避免过度同步:通过
tryAcquire()
非阻塞获取资源- 线程池配合:使用
Executors.newFixedThreadPool()
管理线程生命周期
五、与其他同步机制的对比
1. 与 synchronized 的对比
特性 | synchronized | 并发工具类 |
---|---|---|
灵活性 | 简单互斥 | 支持复杂协作逻辑 |
资源管理 | 自动释放 | 需要手动控制(如 release) |
等待策略 | 无限等待 | 支持超时和中断 |
2. 与 Future 的对比
// Future 方式
Future<String> future = executor.submit(() -> "Result");
String result = future.get(); // 阻塞等待
// CountDownLatch 方式
CountDownLatch latch = new CountDownLatch(1);
executor.submit(() -> {
String result = "Result";
latch.countDown();
});
latch.await();
六、应用案例与最佳实践
1. 并行计算框架
// 使用 CyclicBarrier 实现并行计算
CyclicBarrier barrier = new CyclicBarrier(4);
ExecutorService executor = Executors.newFixedThreadPool(4);
for (int i = 0; i < 4; i++) {
executor.submit(() -> {
try {
// 执行计算
barrier.await(); // 等待所有计算完成
// 合并结果
} catch (Exception e) {
e.printStackTrace();
}
});
}
2. 分布式系统协调
// 使用 Semaphore 控制 API 调用频率
Semaphore semaphore = new Semaphore(10); // 限制每秒 10 次调用
public void apiCall() {
try {
semaphore.acquire();
// 执行 API 调用
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
semaphore.release();
}
}
七、高级特性与未来发展
1. 组合使用技巧
- Phaser + Exchanger:实现多阶段数据交换
- CountDownLatch + Semaphore:控制任务执行顺序和资源分配
2. 低延迟优化
- 使用非阻塞算法:如使用 ConcurrentLinkedQueue 替代阻塞队列
- 调整线程优先级:通过
Thread.setPriority()
优化关键线程响应
3. 硬件级优化
- 利用 CPU 缓存:通过
@Contended
注解减少伪共享- NUMA 感知:结合
AffinityLock
实现线程与 CPU 核绑定
八、总结与实践建议
- 优先使用工具类:避免重复实现复杂同步逻辑
- 理解底层机制:掌握 AQS(AbstractQueuedSynchronizer)原理
- 监控与调优:使用
jconsole
监控线程池和锁状态- 文档与测试:确保工具类使用符合设计契约
Java 的并发工具类通过分层设计和灵活组合,提供了强大的线程协作能力。在实际开发中,需根据具体场景选择合适的工具类,并结合性能监控进行持续优化。未来随着 JVM 和硬件的发展,并发工具类将向更智能、更低延迟的方向演进。