JUC 并发工具包简介
JUC(java.util.concurrent)是 Java 5 引入的并发工具包,它提供了一系列经过充分测试、高性能的并发构建块,极大简化了多线程编程的复杂度。在 JUC 出现之前,开发者只能依赖 synchronized 关键字和 wait/notify 机制来实现线程同步,这种方式不仅容易出错,而且性能有限。
为什么需要 JUC?
传统的 Java 并发编程存在以下问题:
synchronized 的局限性
synchronized 虽然使用简单,但功能有限。它无法中断一个正在等待锁的线程,无法设置锁的超时时间,也无法实现公平锁。当一个线程获取锁后,其他线程只能无限期等待。
线程管理的复杂性
在没有线程池之前,开发者需要手动创建和管理线程。线程是昂贵的系统资源,频繁创建和销毁线程会带来巨大的性能开销。同时,无限制地创建线程可能导致系统资源耗尽。
并发集合的缺失
传统的集合类(如 HashMap、ArrayList)不是线程安全的。虽然可以使用 Collections.synchronizedXXX 方法包装,但这种"全表锁"的方式并发性能很差。
原子操作的困难
实现线程安全的计数器、累加器等操作时,需要使用 synchronized,但这会带来锁竞争的开销。
JUC 的出现正是为了解决这些问题。它提供了更灵活的锁机制、高效的线程池、线程安全的并发集合以及无锁的原子操作类。
JUC 的组成
JUC 包含以下几个核心模块:
1. 锁机制(java.util.concurrent.locks)
提供比 synchronized 更灵活的锁操作:
- ReentrantLock:可重入锁,支持公平/非公平模式、可中断锁、超时获取锁
- ReentrantReadWriteLock:读写锁,允许多个读操作并行执行
- StampedLock:Java 8 引入的乐观读写锁,性能更优
- Condition:条件变量,替代 wait/notify 实现更精细的线程通信
2. 线程池框架(java.util.concurrent)
提供线程的复用和管理:
- Executor:最基础的执行器接口
- ExecutorService:扩展了 Executor,支持任务提交和关闭
- ThreadPoolExecutor:线程池的核心实现类
- ScheduledThreadPoolExecutor:支持定时和周期性任务执行
- Executors:线程池工厂类,提供常用线程池的快捷创建方法
3. 并发集合(java.util.concurrent)
线程安全的集合实现:
- ConcurrentHashMap:高性能的并发哈希表
- CopyOnWriteArrayList:写时复制的线程安全 List
- CopyOnWriteArraySet:写时复制的线程安全 Set
- ConcurrentLinkedQueue:基于链表的无界并发队列
- BlockingQueue 接口及其实现:ArrayBlockingQueue、LinkedBlockingQueue 等
4. 原子类(java.util.concurrent.atomic)
基于 CAS 实现的无锁线程安全操作:
- 基本类型原子类:AtomicInteger、AtomicLong、AtomicBoolean
- 引用类型原子类:AtomicReference、AtomicStampedReference
- 数组类型原子类:AtomicIntegerArray、AtomicLongArray
- 字段更新器:AtomicIntegerFieldUpdater 等
- 累加器:LongAdder、DoubleAdder(高并发下性能优于 AtomicLong)
5. 同步工具类
用于协调多个线程的执行:
- CountDownLatch:一次性栅栏,等待一组线程完成
- CyclicBarrier:可循环使用的栅栏,让一组线程互相等待
- Semaphore:信号量,控制并发访问数量
- Exchanger:两个线程之间交换数据
- Phaser:Java 7 引入,更灵活的同步屏障
6. Fork/Join 框架
Java 7 引入的并行计算框架,采用工作窃取算法,适合处理可递归分解的任务。
JUC 的设计理念
JUC 的设计遵循以下核心原则:
从悲观锁到乐观锁
传统的 synchronized 是悲观锁,假设会发生冲突,每次操作都加锁。JUC 中的原子类采用 CAS(Compare-And-Swap)乐观锁机制,假设不会发生冲突,只在更新时检查,失败后重试。
从全局锁到细粒度锁
Hashtable 使用全局锁,所有操作都串行执行。ConcurrentHashMap 在 JDK 7 中使用分段锁,JDK 8 进一步优化为桶级锁,大大提高了并发度。
从阻塞到非阻塞
传统的 wait/notify 是阻塞式的。JUC 提供了 LockSupport.park/unpark 等非阻塞机制,以及 Future、CompletableFuture 等异步编程模型。
从手动管理到框架支持
线程池框架自动管理线程的生命周期,开发者只需提交任务,无需关心线程的创建、复用和销毁。
学习路线建议
学习 JUC 建议按照以下顺序:
- 理解并发基础:线程状态、线程安全、内存模型(可见性、有序性、原子性)
- 掌握锁机制:从 synchronized 到 ReentrantLock,理解锁的实现原理
- 学习线程池:理解线程池参数、任务队列、拒绝策略
- 使用并发集合:ConcurrentHashMap、BlockingQueue 等
- 应用原子类:CAS 原理、原子类的使用场景
- 掌握同步工具:CountDownLatch、CyclicBarrier、Semaphore 等
- 进阶内容:Fork/Join 框架、CompletableFuture、虚拟线程(Java 21)
小结
JUC 是 Java 并发编程的核心工具包,它解决了传统并发编程的诸多痛点。通过提供灵活的锁机制、高效的线程池、线程安全的并发集合和无锁原子操作,JUC 让开发者能够更轻松地编写高性能、线程安全的并发程序。
在接下来的章节中,我们将深入探讨 JUC 的各个组件,理解它们的原理和使用方法。