Java的JUC并发库及其应用场景
Java 的 JUC(java.util.concurrent) 包是 Java 并发编程的核心工具集,提供了高性能、线程安全的并发类。以下是主要 JUC 类及其应用场景的详细分类解析:
一、锁与同步工具
1. ReentrantLock
- 特点:可重入、支持公平/非公平锁、可中断、超时尝试。
- 应用场景:
- 替代
synchronized
实现更灵活的锁控制。 - 需要尝试获取锁或可中断锁的场景(如死锁恢复)。
- 替代
- 示例:
1
2
3
4
5
6
7ReentrantLock lock = new ReentrantLock();
lock.lock();
try {
// 临界区代码
} finally {
lock.unlock();
}
2. ReentrantReadWriteLock
- 特点:读写分离,读锁共享,写锁独占。
- 应用场景:
- 读多写少的场景(如缓存系统)。
- 示例:
1
2
3ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
rwLock.readLock().lock(); // 读锁
rwLock.writeLock().lock(); // 写锁
3. StampedLock
(JDK 8+)
- 特点:乐观读锁、写锁可降级为读锁。
- 应用场景:
- 极高并发读写场景(比
ReentrantReadWriteLock
性能更高)。
- 极高并发读写场景(比
- 示例:
1
2
3
4
5StampedLock lock = new StampedLock();
long stamp = lock.tryOptimisticRead(); // 乐观读
if (!lock.validate(stamp)) {
stamp = lock.readLock(); // 退化为悲观读
}
二、并发容器
1. ConcurrentHashMap
- 特点:分段锁(JDK 7)或 CAS + synchronized(JDK 8+),高并发读写。
- 应用场景:
- 高并发键值存储(如缓存、计数器)。
- 示例:
1
2ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
map.computeIfAbsent("key", k -> 1); // 原子操作
2. CopyOnWriteArrayList
- 特点:写时复制,读操作无锁。
- 应用场景:
- 读多写少的列表(如监听器列表)。
- 示例:
1
2CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
list.add("item"); // 写操作复制整个数组
3. BlockingQueue
接口
- 实现类:
ArrayBlockingQueue
:固定大小数组队列。LinkedBlockingQueue
:可选边界链表队列。PriorityBlockingQueue
:优先级阻塞队列。
- 应用场景:
- 生产者-消费者模型(如线程池任务队列)。
- 示例:
1
2
3BlockingQueue<String> queue = new ArrayBlockingQueue<>(10);
queue.put("item"); // 阻塞插入
String item = queue.take(); // 阻塞取出
三、线程协作工具
1. CountDownLatch
- 特点:一次性屏障,等待多个任务完成。
- 应用场景:
- 主线程等待所有子线程初始化完成。
- 示例:
1
2
3
4
5CountDownLatch latch = new CountDownLatch(3);
// 子线程
latch.countDown();
// 主线程
latch.await();
2. CyclicBarrier
- 特点:可重复使用的同步屏障。
- 应用场景:
- 多阶段任务同步(如并行计算分阶段汇总)。
- 示例:
1
2CyclicBarrier barrier = new CyclicBarrier(3, () -> System.out.println("All threads reached barrier"));
barrier.await(); // 线程阻塞直到所有线程到达
3. Semaphore
- 特点:控制并发访问资源的线程数。
- 应用场景:
- 限流(如数据库连接池)。
- 示例:
1
2
3Semaphore semaphore = new Semaphore(5); // 允许5个线程并发
semaphore.acquire(); // 获取许可
semaphore.release(); // 释放许可
4. Phaser
(JDK 7+)
- 特点:动态调整的同步屏障,支持多阶段。
- 应用场景:
- 复杂分阶段任务(如游戏多关卡加载)。
- 示例:
1
2Phaser phaser = new Phaser(3); // 注册3个线程
phaser.arriveAndAwaitAdvance(); // 等待所有线程完成当前阶段
四、线程池与异步任务
1. ThreadPoolExecutor
- 核心参数:
corePoolSize
:核心线程数。maximumPoolSize
:最大线程数。keepAliveTime
:空闲线程存活时间。workQueue
:任务队列(如LinkedBlockingQueue
)。
- 应用场景:
- 管理线程资源,避免频繁创建销毁线程。
- 示例:
1
2
3
4ExecutorService executor = new ThreadPoolExecutor(
2, 10, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100)
);
executor.submit(() -> System.out.println("Task executed"));
2. ForkJoinPool
- 特点:工作窃取算法,适合分治任务。
- 应用场景:
- 并行计算(如大规模数组排序)。
- 示例:
1
2
3
4
5
6
7
8ForkJoinPool pool = new ForkJoinPool();
pool.invoke(new RecursiveTask<Integer>() {
protected Integer compute() {
// 分治逻辑
return null;
}
});
3. CompletableFuture
(JDK 8+)
- 特点:异步编程,支持链式调用和组合。
- 应用场景:
- 非阻塞异步任务编排(如微服务调用聚合)。
- 示例:
1
2
3CompletableFuture.supplyAsync(() -> "Hello")
.thenApplyAsync(s -> s + " World")
.thenAccept(System.out::println);
五、原子操作类
1. AtomicInteger
/AtomicLong
- 特点:CAS 实现原子操作。
- 应用场景:
- 计数器、序号生成。
- 示例:
1
2AtomicInteger counter = new AtomicInteger(0);
counter.incrementAndGet(); // 原子自增
2. AtomicReference
- 特点:原子更新对象引用。
- 应用场景:
- 无锁数据结构(如栈、队列)。
- 示例:
1
2AtomicReference<String> ref = new AtomicReference<>("old");
ref.compareAndSet("old", "new"); // CAS 更新
3. LongAdder
(JDK 8+)
- 特点:分段累加,高并发下性能优于
AtomicLong
。 - 应用场景:
- 高频统计(如实时点击量计数)。
- 示例:
1
2LongAdder adder = new LongAdder();
adder.increment();
六、应用场景总结
场景 | 推荐 JUC 类 |
---|---|
高并发缓存 | ConcurrentHashMap |
生产者-消费者 | BlockingQueue |
任务并行执行 | ForkJoinPool |
多线程等待统一信号 | CountDownLatch /CyclicBarrier |
资源池管理(如连接池) | Semaphore |
无锁算法实现 | AtomicXXX 系列 |
异步任务编排 | CompletableFuture |
七、最佳实践
- 优先使用并发容器:替代
Collections.synchronizedXXX()
。 - 避免过早优化:在确实需要时再使用低级工具(如
AQS
)。 - 注意资源清理:线程池使用后调用
shutdown()
。 - 合理设置线程池参数:根据任务类型(CPU/IO 密集型)调整大小。
通过合理选择 JUC 类,可以显著提升 Java 并发程序的性能和可维护性。