Java并发工具
Java并发工具位于java.util.concurrent
包(JUC),用于简化多线程编程,提高性能与线程安全性。以下是核心工具分类及使用指南(涵盖JDK8+新特性):
1. 线程池(Executor框架)
一、是什么?
通过ExecutorService
管理线程生命周期,避免频繁创建/销毁线程的开销。JDK8+新增CompletableFuture
支持异步编程。
二、解决什么问题
减少线程创建开销,控制并发资源(如数据库连接),避免线程失控导致OOM。
三、核心方法
Executors.newFixedThreadPool(n)
: 固定大小线程池executor.submit(Runnable/Callable)
: 提交任务executor.shutdown()
: 优雅关闭
四、应用场景
Web服务器请求处理、批量数据处理。
五、Java示例
java
ExecutorService executor = Executors.newFixedThreadPool(4);
executor.submit(() -> System.out.println("Task running"));
executor.shutdown();
2. 锁机制(Lock接口)
一、是什么?
替代synchronized
的更灵活锁,如ReentrantLock
(可重入锁)、StampedLock
(JDK8新增,乐观读锁)。
二、解决什么问题
解决synchronized
无法中断、超时等待等问题;StampedLock
优化读多写少场景。
三、核心方法
lock.lock()
: 获取锁lock.tryLock(timeout)
: 尝试获取锁(支持超时)stampedLock.tryOptimisticRead()
: 乐观读(不阻塞写)
四、应用场景
缓存更新(读写分离)、资源争用控制。
五、Java示例
java
ReentrantLock lock = new ReentrantLock();
lock.lock();
try { /* 临界区 */ }
finally { lock.unlock(); }
// StampedLock示例(JDK8+)
StampedLock sl = new StampedLock();
long stamp = sl.tryOptimisticRead(); // 乐观读
if (!sl.validate(stamp)) { // 检查是否被写操作修改
stamp = sl.readLock(); // 升级为悲观读
}
3. 原子类(Atomic Classes)
一、是什么?
如AtomicInteger
,通过CAS(Compare-And-Swap)实现无锁线程安全操作。
二、解决什么问题
替代synchronized
实现轻量级原子操作(如计数器),避免锁竞争。
三、核心方法
atomic.get()
: 获取值atomic.incrementAndGet()
: 原子自增atomic.updateAndGet(x -> x * 2)
: (JDK8+)函数式更新
四、应用场景
计数器、状态标志。
五、Java示例
java
AtomicInteger count = new AtomicInteger(0);
count.incrementAndGet(); // 线程安全自增
4. 并发集合
一、是什么?
线程安全的集合类,如ConcurrentHashMap
(JDK8优化为CAS+synchronized)、CopyOnWriteArrayList
。
二、解决什么问题
解决Collections.synchronizedList
等同步容器的性能瓶颈。
三、核心方法
map.putIfAbsent(key, value)
: 仅当key不存在时插入list.add(e)
: 自动加锁(CopyOnWriteArrayList)
四、应用场景
缓存(ConcurrentHashMap)、读多写少的列表(CopyOnWriteArrayList)。
5. 同步工具类
工具 | 作用 | JDK8+增强 |
---|---|---|
CountDownLatch | 等待多个任务完成 | - |
CyclicBarrier | 多线程相互等待至屏障点 | - |
Semaphore | 控制资源访问数量(如限流) | - |
CompletableFuture | 异步编程链式调用 | ✅ 支持thenApply() 等组合操作 |
CountDownLatch示例:
java
CountDownLatch latch = new CountDownLatch(3);
// 多个线程调用 latch.countDown()
latch.await(); // 主线程等待所有任务完成
CompletableFuture示例(JDK8+):
java
CompletableFuture.supplyAsync(() -> "Hello")
.thenApply(s -> s + " World")
.thenAccept(System.out::println); // 输出 "Hello World"
区别总结
工具 | 适用场景 | 特性 |
---|---|---|
synchronized | 简单同步块 | JVM内置,无需手动释放锁 |
ReentrantLock | 需要超时/中断的复杂场景 | 可响应中断,支持公平锁 |
StampedLock | 读多写少 | 乐观读提升性能 |
CompletableFuture | 异步任务编排 | 链式调用,避免回调地狱 |
重要注意事项
- 避免死锁:按固定顺序获取锁,使用
tryLock
设置超时。 - 线程池参数:
corePoolSize
:常驻线程数workQueue
:任务队列(如LinkedBlockingQueue
)- 拒绝策略:
AbortPolicy
(默认抛异常)
- 原子类局限:
- 适用于单一变量,复合操作仍需锁。
- CompletableFuture:
- 默认使用
ForkJoinPool
,可自定义线程池。
- 默认使用
总结
Java并发工具的核心是平衡性能与线程安全:
- 优先使用
ConcurrentHashMap
、原子类等无锁结构; - IO密集型任务用线程池;
- 复杂异步逻辑用
CompletableFuture
; - 读多写少场景选
StampedLock
。
最佳实践:避免过早优化,先用高阶工具(如并发集合),再针对瓶颈细化锁策略。