第六章:多线程与并发
6.5 并发工具类(Executor, Semaphore, CountDownLatch等)
Java提供了丰富的并发工具类来简化多线程编程,提高开发效率和程序性能。本节将介绍几种常用的并发工具类及其应用场景。
1. Executor框架
Executor框架是Java 5引入的线程池管理工具,用于解耦任务提交与任务执行。
核心接口与类
Executor: 基础接口,定义execute(Runnable)方法ExecutorService: 扩展Executor,提供生命周期管理ThreadPoolExecutor: 可配置的线程池实现Executors: 工厂类,提供常用线程池配置
常用线程池类型
// 固定大小线程池
ExecutorService fixedPool = Executors.newFixedThreadPool(5);
// 缓存线程池(自动扩容)
ExecutorService cachedPool = Executors.newCachedThreadPool();
// 单线程池(保证任务顺序执行)
ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
// 定时任务线程池
ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(3);
2. Semaphore(信号量)
控制同时访问特定资源的线程数量,常用于限流场景。
基本用法
Semaphore semaphore = new Semaphore(3); // 允许3个线程同时访问
void accessResource() throws InterruptedException {
semaphore.acquire(); // 获取许可
try {
// 访问共享资源
} finally {
semaphore.release(); // 释放许可
}
}
应用场景
- 数据库连接池管理
- 限流控制
- 资源池实现
3. CountDownLatch(倒计时门闩)
允许一个或多个线程等待其他线程完成操作。
基本用法
CountDownLatch latch = new CountDownLatch(3); // 需要等待3个任务完成
// 工作线程
void doWork() {
// 执行任务
latch.countDown(); // 计数器减1
}
// 主线程
void main() throws InterruptedException {
startWorkers(); // 启动3个工作线程
latch.await(); // 等待所有工作完成
// 继续后续操作
}
应用场景
- 并行任务同步
- 服务启动依赖检查
- 多线程测试
4. CyclicBarrier(循环屏障)
让一组线程到达一个屏障时被阻塞,直到最后一个线程到达屏障时,所有线程才会继续执行。
基本用法
CyclicBarrier barrier = new CyclicBarrier(3, () -> {
// 所有线程到达屏障后执行的回调
});
void worker() throws Exception {
// 第一阶段工作
barrier.await();
// 第二阶段工作
}
与CountDownLatch的区别
- 可重复使用(reset)
- 支持回调函数
- 所有线程互相等待
5. Future与CompletableFuture
Future
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(() -> {
Thread.sleep(1000);
return "Result";
});
// 阻塞获取结果
String result = future.get();
CompletableFuture(Java 8+)
CompletableFuture.supplyAsync(() -> "Hello")
.thenApply(s -> s + " World")
.thenAccept(System.out::println);
6. 其他实用工具类
- Phaser: 更灵活的屏障实现,支持动态调整参与线程数
- Exchanger: 两个线程间的数据交换点
- LockSupport: 线程阻塞/唤醒的基础工具
最佳实践
- 优先使用线程池而非直接创建线程
- 合理设置线程池大小(CPU密集型 vs IO密集型)
- 注意资源清理,避免线程泄漏
- 使用合适的并发工具简化代码
- 考虑使用更高层次的并发框架(如Akka、RxJava)
通过合理使用这些并发工具类,可以显著提高多线程程序的可靠性和性能,同时降低开发复杂度。
