CopyOnWriteArraySet适用于读多写少的并发场景,基于写时复制机制实现线程安全,读操作无需加锁且遍历时不会抛出ConcurrentModificationException,适合用于监听器列表、事件订阅系统等频繁读取、较少修改的场景,但写操作需复制整个数组,开销大、内存占用高,不适用于写多环境。

在Java中,CopyOnWriteArraySet 是一个线程安全的集合类,适用于读多写少的并发场景。它内部基于 CopyOnWriteArrayList 实现,通过“写时复制”机制来保证线程安全。也就是说,每次修改操作(如添加元素)都会创建一个新的数组副本,而读操作不需要加锁,因此可以高效并发执行。
何时使用 CopyOnWriteArraySet
适合以下情况:
- 集合被频繁遍历或读取
- 添加、删除等修改操作较少
- 需要线程安全且避免显式同步
常见于监听器列表、事件订阅系统等并发读取多、变更少的场景。
基本使用方法
创建和操作 CopyOnWriteArraySet 非常简单,和普通 Set 类似:
立即学习“Java免费学习笔记(深入)”;
Shopxp购物系统历经多年的考验,并在推出shopxp免费购物系统下载之后,收到用户反馈的各种安全、漏洞、BUG、使用问题进行多次修补,已经从成熟迈向经典,再好的系统也会有问题,在完善的系统也从在安全漏洞,该系统完全开源可编辑,当您下载这套商城系统之后,可以结合自身的技术情况,进行开发完善,当然您如果有更好的建议可从官方网站提交给我们。Shopxp网上购物系统完整可用,无任何收费项目。该系统经过
import java.util.concurrent.CopyOnWriteArraySet;
public class Example {
public static void main(String[] args) {
// 创建实例
CopyOnWriteArraySet set = new CopyOnWriteArraySet<>();
// 添加元素
set.add("apple");
set.add("banana");
set.add("cherry");
// 尝试重复添加(不会生效,Set 不允许重复)
boolean added = set.add("apple");
System.out.println("Apple already exists: " + !added); // true
// 遍历元素(安全,并发读没问题)
for (String item : set) {
System.out.println(item);
}
// 删除元素
set.remove("banana");
// 输出当前内容
System.out.println("After removal: " + set);
}
}
线程安全的迭代示例
它的最大优势是:即使在遍历过程中有其他线程修改集合,也不会抛出 ConcurrentModificationException。
import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArraySet;
public class ThreadSafeIteration {
private static final CopyOnWriteArraySet set = new CopyOnWriteArraySet<>();
public static void main(String[] args) {
// 主线程添加初始数据
set.addAll(java.util.Arrays.asList(1, 2, 3, 4, 5));
// 启动一个线程不断遍历
new Thread(() -> {
for (int i = 0; i < 10; i++) {
Iterator it = set.iterator();
while (it.hasNext()) {
Integer val = it.next();
System.out.println("Reading: " + val);
try {
Thread.sleep(100); // 模拟处理时间
} catch (InterruptedException e) { break; }
}
}
}).start();
// 另一个线程定时添加元素
new Thread(() -> {
for (int i = 6; i <= 10; i++) {
set.add(i);
System.out.println("Added: " + i);
try {
Thread.sleep(300);
} catch (InterruptedException e) { return; }
}
}).start();
}
}
上述代码中,即使一个线程正在遍历集合,另一个线程同时添加元素,程序也不会出错。这是因为迭代器基于快照,看到的是创建时的数据状态。
注意事项与局限性
虽然 CopyOnWriteArraySet 线程安全,但也有明显缺点:
如果写操作频繁,建议考虑 ConcurrentHashMap.keySet() 或使用同步包装的 HashSet。
基本上就这些。CopyOnWriteArraySet 是一种特殊用途的集合,用对了场景能简化并发编程,但要警惕其性能代价。









