fail-safe迭代器基于集合快照而非实时状态遍历,不抛concurrentmodificationexception;其原理是创建独立副本(如toarray或arraylist复制),所有操作仅作用于副本,与原集合解耦,典型实现为copyonwritearraylist/set。

Java 中的 fail-safe 迭代器不依赖原始集合的实时状态,而是基于集合某一时刻的不可变快照(copy)进行遍历,因此即使原集合被其他线程修改,迭代过程也不会抛出 ConcurrentModificationException。
底层原理:迭代器持有独立副本
fail-safe 迭代器在创建时,会调用集合的内部方法(如 toArray() 或 new ArrayList(original))生成一个完整副本。后续所有 next()、hasNext() 操作都只访问这个副本,与原集合完全解耦。
- 副本通常为数组或不可变列表,创建后不再更新
- 原集合的 add/remove/clear 等操作对副本无影响
- 内存开销存在(尤其大数据集),但换来线程安全的遍历能力
典型实现类:CopyOnWriteArrayList / CopyOnWriteArraySet
这两个类是 fail-safe 的标准实践。以 CopyOnWriteArrayList 为例:
- 每次写操作(add/set/remove)都会新建数组,复制旧数据 + 修改内容,再原子替换引用
-
iterator()返回的迭代器,其内部数组引用指向创建时的快照 - 即使遍历时另一线程已修改集合,迭代器仍按旧快照顺序输出
使用注意:快照是“过去式”,不是实时视图
fail-safe 的代价是无法反映迭代期间发生的变更:
- 新增元素不会出现在当前迭代中
- 删除元素仍可能被遍历到(如果它在快照里)
- 适合读多写少场景(如监听器列表、配置项缓存)
手动实现简易 fail-safe 迭代(不推荐生产,仅理解逻辑)
可通过显式拷贝构造迭代器:
ListList
Iterator
original.add("d"); // 不影响 it
while (it.hasNext()) System.out.println(it.next()); // 输出 a b c
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











