Java 多线程并发编程:并发容器与线程协作实战
💡 学习目标:掌握 JAVA 中常用并发容器的特性与适用场景,理解线程间协作的核心原理,能够运用并发容器和协作工具解决实际并发问题。
💡 学习重点:并发容器与普通容器的区别、ConcurrentHashMap 核心原理、CountDownLatch/CyclicBarrier/Semaphore 的使用、生产者消费者模式实现。
1.1 为什么需要并发容器?
在多线程场景下,普通的集合容器(如 HashMap、ArrayList)是线程不安全的。多个线程同时对其进行读写操作时,会导致数据错乱、ConcurrentModificationException 异常等问题。
⚠️ 注意事项:即使使用 Collections.synchronizedXXX() 方法包装普通容器,也只是通过 synchronized 实现简单的加锁。这种方式锁粒度较粗,并发性能较低。
✅ 核心结论:并发容器是 JAVA 为多线程场景设计的高性能容器。它们通过细粒度锁或无锁算法实现线程安全,能够在保证数据一致性的同时,大幅提升并发访问效率。
1.2 常用并发容器详解
1.2.1 ConcurrentHashMap:高效并发哈希表
ConcurrentHashMap 是 HashMap 的并发安全版本,是日常开发中使用频率最高的并发容器。
1.2.1.1 核心特点
- 分段锁(JDK1.7)→ CAS + 同步锁(JDK1.8)
- JDK1.7 采用分段锁机制,将数据分成多个 Segment。每个 Segment 独立加锁,不同 Segment 的操作互不阻塞。
- JDK1.8 抛弃分段锁,采用 CAS +
synchronized实现。锁粒度缩小到单个 Node 节点,并发性能进一步提升。
- 支持高并发读写:读操作无锁(通过
volatile保证可见性),写操作仅锁定当前节点,不会阻塞其他操作。 - 不允许
null键值:与HashMap不同,ConcurrentHashMap的键和值都不能为null,避免歧义。
1.2.1.2 核心方法使用示例
import java.util.concurrent.ConcurrentHashMap;
/**
* ConcurrentHashMap 实战示例
*/
public class ConcurrentHashMapDemo {
InterruptedException {
ConcurrentHashMap<String, Integer> map = <>();
map.put(, );
map.put(, );
map.put(, );
(() -> {
( ; i < ; i++) {
map.computeIfPresent(, (k, v) -> v + );
System.out.println(Thread.currentThread().getName() + + map.get());
}
}, );
(() -> {
( ; i < ; i++) {
map.computeIfPresent(, (k, v) -> v + );
System.out.println(Thread.currentThread().getName() + + map.get());
}
}, );
thread1.start();
thread2.start();
thread1.join();
thread2.join();
map.forEach((k, v) -> System.out.println(k + + v));
}
}


