Skip to content

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异步任务编排链式调用,避免回调地狱

重要注意事项

  1. 避免死锁:按固定顺序获取锁,使用tryLock设置超时。
  2. 线程池参数
    • corePoolSize:常驻线程数
    • workQueue:任务队列(如LinkedBlockingQueue
    • 拒绝策略:AbortPolicy(默认抛异常)
  3. 原子类局限
    • 适用于单一变量,复合操作仍需锁。
  4. CompletableFuture
    • 默认使用ForkJoinPool,可自定义线程池。

总结

Java并发工具的核心是平衡性能与线程安全

  • 优先使用ConcurrentHashMap、原子类等无锁结构;
  • IO密集型任务用线程池;
  • 复杂异步逻辑用CompletableFuture
  • 读多写少场景选StampedLock
    最佳实践:避免过早优化,先用高阶工具(如并发集合),再针对瓶颈细化锁策略。