Melon Playground甜瓜游乐场
98.73M · 2026-03-22
Java 为高并发场景专门设计的高性能线程安全集合。它们各自采用了不同的并发控制策略,适用于不同的场景。下面逐一介绍它们的实现原理、特点和适用场景。
| 线程安全类 | 对应线程不安全类 | 说明 |
|---|---|---|
ConcurrentHashMap | HashMap | 无序键值对,高并发场景替代 HashMap 或 Hashtable |
ConcurrentSkipListMap | TreeMap | 有序键值对(基于跳表),高并发场景替代 TreeMap |
ConcurrentSkipListSet | TreeSet | 有序元素集(底层基于 ConcurrentSkipListMap),替代 TreeSet |
CopyOnWriteArrayList | ArrayList | 读多写少场景替代 ArrayList,避免 ConcurrentModificationException |
CopyOnWriteArraySet | HashSet | 读多写少场景替代 HashSet(底层使用 CopyOnWriteArrayList 实现) |
HashMap 类似(数组 + 链表 + 红黑树),写操作只锁定当前操作的桶(或树节点),读操作几乎不加锁(使用 volatile 保证可见性)。Hashtable 或 Collections.synchronizedMap。null 键或值。putIfAbsent()、remove()、replace() 等。ConcurrentModificationException,但遍历时可能不反映最新修改)。基于 跳表(Skip List) 数据结构,是一种以空间换时间的并发有序 Map。跳表通过多层索引实现近似二分查找,插入、删除、查找的平均时间复杂度为 O(log n) 。
ConcurrentNavigableMap 接口,提供了 subMap()、headMap()、tailMap() 等视图方法。null 键或值。TreeMap 的并发替代品。本质上是一个 ConcurrentSkipListMap 的包装,所有元素作为 Map 的键,值统一为 Boolean.TRUE。
Comparator 排序)。采用 写时复制(Copy-On-Write) 策略:
volatile 数组作为存储。get()、iterator())直接访问当前数组,不加锁,性能极高。add()、set()、remove())先复制一份新数组,在新数组上修改,然后将数组引用指向新数组。复制过程中,读操作仍可并发访问旧数组,保证读线程不被阻塞。ConcurrentModificationException。直接 包装 CopyOnWriteArrayList,所有操作委托给内部的 CopyOnWriteArrayList。
AbstractSet,元素唯一性通过内部 List 的 addIfAbsent() 保证。CopyOnWriteArrayList 相同的读写特性:读无锁、写复制。contains() 操作是 O(n) 复杂度(相对于 HashSet 的 O(1))。CopyOnWriteArrayList 类似,适用于 读多写少、且元素唯一 的场景。| 集合类 | 数据结构 | 是否有序 | 锁机制 | 读写特性 | 适用场景 |
|---|---|---|---|---|---|
ConcurrentHashMap | 数组+链表+红黑树 | 无序 | JDK 1.8+:CAS + synchronized 锁桶/节点 | 读几乎无锁,写锁粒度细 | 高并发通用 Map |
ConcurrentSkipListMap | 跳表 | 有序 | CAS + 节点锁 | 读写均高效 | 需要有序、高并发 Map |
ConcurrentSkipListSet | 跳表(包装 Map) | 有序 | 同 ConcurrentSkipListMap | 读写均高效 | 需要有序、高并发 Set |
CopyOnWriteArrayList | 数组(写时复制) | 保持插入顺序 | 写时复制(写锁),读无锁 | 读极快,写慢 | 读远多于写的 List |
CopyOnWriteArraySet | 数组(包装 List) | 保持插入顺序 | 同 CopyOnWriteArrayList | 读极快,写慢 | 读远多于写的 Set |
ConcurrentHashMap;若需要键有序,使用 ConcurrentSkipListMap。ConcurrentHashMap 包装的 newKeySet()(JDK 8+,ConcurrentHashMap.newKeySet());若需有序,用 ConcurrentSkipListSet;若读远多于写且元素唯一性要求不高,可用 CopyOnWriteArraySet。CopyOnWriteArrayList;否则可考虑用 Collections.synchronizedList 或 ConcurrentLinkedQueue 等替代(但需注意 ConcurrentLinkedQueue 不是 List 接口)。