答案:CopyOnWrite机制通过写时复制实现线程安全,读操作无锁且高效,适用于读多写少场景;CopyOnWriteArrayList和CopyOnWriteArraySet分别作为List和Set的并发实现,底层采用数组复制保证线程安全,但写操作开销大,不适合频繁修改或大数据量场景。
在多线程编程中,安全地操作集合类是一个常见挑战。Java 提供了 CopyOnWriteArrayList 和 CopyOnWriteArraySet 来解决并发修改的问题,特别适用于读多写少的场景。
“写时复制”(Copy-On-Write)是一种并发控制策略。当需要修改集合内容时,不直接在原数组上操作,而是先复制一份新的数组,在新数组上完成修改,然后将引用指向新数组。整个过程对读操作无阻塞。
这种机制保证了读操作的高效性和线程安全性,因为读操作始终基于一个不变的数组快照。
CopyOnWriteArrayList 是 List 接口的线程安全实现,适合并发环境下频繁读取、较少增删改的场景。
常用方法示例:add(E e):添加元素,会触发数组复制remove(Object o):删除元素,同样复制底层数组get(int index):获取元素,无锁,非常快iterator():返回弱一致性的迭代器(基于快照)示例代码:
CopyOnWriteArrayListlist = new CopyOnWriteArrayList<>(); list.add("A"); list.add("B"); // 多线程读取安全 new Thread(() -> list.forEach(System.out::println)).start();

CopyOnWriteArraySet 内部基于 CopyOnWriteArrayList 实现,确保元素唯一性,是线程安全的 Set 实现。
它并不是通过哈希表去重,而是在每次添加前遍历已有元素判断是否已存在,因此性能不如 HashSet,但在并发读多写少时表现稳定。
关键特性:add(E e) 时,若元素已存在,则添加失败(返回 false)示例代码:
CopyOnWriteArraySetset = new CopyOnWriteArraySet<>(); set.add("user1"); set.add("user2"); set.add("user1"); // 重复元素,不会加入 System.out.println(set.size()); // 输出 2
这两个类都适用于读远多于写的并发环境,比如监听器列表、配置缓存、白名单等。
需要注意的几点:基本上就这些。理解 CopyOnWrite 的核心思想,能帮助你在合适的场景下合理选择并发集合类。