java多线程安全集合

Java 为高并发场景专门设计的高性能线程安全集合。它们各自采用了不同的并发控制策略,适用于不同的场景。下面逐一介绍它们的实现原理、特点和适用场景。

介绍:这些线程安全的并发集合分别对应以下线程不安全的集合类:

线程安全类 对应线程不安全类 说明
ConcurrentHashMap HashMap 无序键值对,高并发场景替代 HashMapHashtable
ConcurrentSkipListMap TreeMap 有序键值对(基于跳表),高并发场景替代 TreeMap
ConcurrentSkipListSet TreeSet 有序元素集(底层基于 ConcurrentSkipListMap),替代 TreeSet
CopyOnWriteArrayList ArrayList 读多写少场景替代 ArrayList,避免 ConcurrentModificationException
CopyOnWriteArraySet HashSet 读多写少场景替代 HashSet(底层使用 CopyOnWriteArrayList 实现)

1. ConcurrentHashMap

底层实现

  • JDK 1.7 :采用 分段锁(Segment) 技术,将整个 Map 分成多个 Segment,每个 Segment 独立加锁,允许多个线程同时操作不同 Segment。
  • JDK 1.8+ :取消分段锁,改用 CAS + synchronized 对节点进行更细粒度的控制。底层数据结构与 HashMap 类似(数组 + 链表 + 红黑树),写操作只锁定当前操作的桶(或树节点),读操作几乎不加锁(使用 volatile 保证可见性)。

特点

  • 高并发读写,吞吐量远高于 HashtableCollections.synchronizedMap
  • 不允许 null 键或值。
  • 提供原子性复合操作:putIfAbsent()remove()replace() 等。
  • 迭代器是 弱一致性 (不会抛出 ConcurrentModificationException,但遍历时可能不反映最新修改)。

适用场景

  • 高并发环境下的大规模 Map 操作,是 首选的并发 Map 实现

2. ConcurrentSkipListMap

底层实现

基于 跳表(Skip List) 数据结构,是一种以空间换时间的并发有序 Map。跳表通过多层索引实现近似二分查找,插入、删除、查找的平均时间复杂度为 O(log n)

特点

  • 线程安全,支持高并发读写。
  • 保持键的有序性 ,实现 ConcurrentNavigableMap 接口,提供了 subMap()headMap()tailMap() 等视图方法。
  • 并发控制采用 CAS 和锁(在跳表节点层面精细控制),性能优秀。
  • 不允许 null 键或值。

适用场景

  • 需要 有序且高并发 的 Map,例如实现并发缓存、排行榜、范围查询等。
  • TreeMap 的并发替代品。

3. ConcurrentSkipListSet

底层实现

本质上是一个 ConcurrentSkipListMap 的包装 ,所有元素作为 Map 的键,值统一为 Boolean.TRUE

特点

  • 线程安全、有序(按自然顺序或自定义 Comparator 排序)。
  • 支持高并发读写。
  • 迭代器是弱一致性。

适用场景

  • 需要 有序且高并发 的 Set,例如需要快速判断元素是否存在、保持元素有序,且允许多线程并发访问。

4. CopyOnWriteArrayList

底层实现

采用 写时复制(Copy-On-Write) 策略:

  • 内部维护一个 volatile 数组作为存储。
  • 读操作get()iterator())直接访问当前数组,不加锁,性能极高。
  • 写操作add()set()remove())先复制一份新数组,在新数组上修改,然后将数组引用指向新数组。复制过程中,读操作仍可并发访问旧数组,保证读线程不被阻塞。

特点

  • 读操作无锁,写操作因复制数组而开销较大(适合读多写少的场景)。
  • 迭代器是 快照 风格,创建后不会受后续修改影响,永远不会抛出 ConcurrentModificationException
  • 内存占用较高(写操作会临时产生两份数组)。

适用场景

  • 读远多于写 的集合,例如配置信息、监听器列表、缓存等。

5. CopyOnWriteArraySet

底层实现

直接 包装 CopyOnWriteArrayList ,所有操作委托给内部的 CopyOnWriteArrayList

特点

  • 继承 AbstractSet,元素唯一性通过内部 List 的 addIfAbsent() 保证。
  • 具备与 CopyOnWriteArrayList 相同的读写特性:读无锁、写复制。
  • 由于底层是 List,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

选型建议

  • Map :默认首选 ConcurrentHashMap;若需要键有序,使用 ConcurrentSkipListMap
  • Set :若需高并发且无需排序,可考虑 ConcurrentHashMap 包装的 newKeySet()(JDK 8+,ConcurrentHashMap.newKeySet());若需有序,用 ConcurrentSkipListSet;若读远多于写且元素唯一性要求不高,可用 CopyOnWriteArraySet
  • List :若读远多于写,用 CopyOnWriteArrayList;否则可考虑用 Collections.synchronizedListConcurrentLinkedQueue 等替代(但需注意 ConcurrentLinkedQueue 不是 List 接口)。
相关推荐
末央&10 小时前
【天机论坛】项目环境搭建和数据库设计
java·数据库
枫叶落雨22210 小时前
ShardingSphere 介绍
java
花花鱼10 小时前
Spring Security 与 Spring MVC
java·spring·mvc
言慢行善11 小时前
sqlserver模糊查询问题
java·数据库·sqlserver
专吃海绵宝宝菠萝屋的派大星11 小时前
使用Dify对接自己开发的mcp
java·服务器·前端
大数据新鸟11 小时前
操作系统之虚拟内存
java·服务器·网络
Tong Z11 小时前
常见的限流算法和实现原理
java·开发语言
凭君语未可11 小时前
Java 中的实现类是什么
java·开发语言
He少年11 小时前
【基础知识、Skill、Rules和MCP案例介绍】
java·前端·python
克里斯蒂亚诺更新11 小时前
myeclipse的pojie
java·ide·myeclipse