CopyOnWriteArraySet是线程安全的Set,底层基于CopyOnWriteArrayList实现写时复制机制:读操作无锁高效,写操作通过复制数组加锁保证安全,适用于读多写少场景(如监听器列表),但写开销大、不支持实时迭代和null元素。

CopyOnWriteArraySet 是 Java 并发包(java.util.concurrent)中提供的线程安全集合,底层基于 CopyOnWriteArrayList 实现,适合读多写少的场景。它通过“写时复制”机制保证线程安全:每次修改(add/remove)都会创建新数组,而读操作无锁、不阻塞。
为什么用 CopyOnWriteArraySet 而不是普通 HashSet?
普通 HashSet 非线程安全,多线程下直接使用可能抛出 ConcurrentModificationException 或导致数据不一致。虽然可用 Collections.synchronizedSet() 包装,但所有操作(包括遍历)都加同一把锁,性能差;而 CopyOnWriteArraySet 读操作完全无锁,适合高并发读、低频写的场景(如监听器列表、配置白名单等)。
基本用法:声明与添加元素
直接实例化即可,无需额外同步:
- 初始化:
CopyOnWriteArraySetset = new CopyOnWriteArraySet(); - 添加元素:
set.add("item1");—— 线程安全,重复添加自动忽略(Set 语义) - 检查存在:
set.contains("item1")—— 无锁,高性能 - 遍历:
for (String s : set) { ... }—— 不会因其他线程修改而抛异常,看到的是某次快照
注意写操作的开销和适用边界
每次 add、remove 或 clear 都会复制整个底层数组,时间复杂度为 O(n),内存占用翻倍。因此:
- 避免在高频写场景(如每秒数千次增删)中使用
- 集合大小不宜过大(几百到几千元素较合适)
- 若需频繁写+强一致性,考虑
ConcurrentHashMap.newKeySet()(JDK 8+),它基于分段锁,写性能更好
常见误用与替代建议
不要把它当作通用并发 Set 的“银弹”:
- 不能保证实时性:迭代时看不到其他线程刚 add 的元素(因为看到的是旧快照)
- 不支持 null 元素(抛
NullPointerException) - 如果需要排序或自定义比较器,它不支持 —— 此时可考虑
ConcurrentSkipListSet - 仅当读远大于写且元素量适中时,才是最优解
不复杂但容易忽略细节,选对场景才能发挥它的优势。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











