Java中Iterator非线程安全,安全遍历的关键是避免共享迭代器状态;推荐方案包括:1.用CopyOnWriteArrayList的快照迭代器(读多写少);2.各线程创建独立迭代器;3.用AtomicInteger手动索引;4.提前切分数据彻底隔离。

Java 中 Iterator 本身不是线程安全的,多线程共享同一个迭代器必然导致游标错乱、重复遍历、跳过元素,甚至抛出 ConcurrentModificationException。所谓“安全遍历”,关键不是给迭代器加锁,而是**避免共享迭代器状态**,从源头隔离线程间的游标竞争。
用 CopyOnWriteArrayList 的弱一致性迭代器
这是最直接的方案,适合读多写少场景(如监听器列表、配置项缓存):
- 它的
iterator()返回的是创建时刻的数组快照,遍历时完全不受其他线程增删操作影响 - 不会抛
ConcurrentModificationException,也不会看到新插入或刚删除的元素 - 写操作开销大(每次修改都复制整个数组),不适合高频更新的集合
每个线程创建独立迭代器
对普通集合(如 ArrayList、LinkedList),不共享迭代器是底线:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 主线程准备数据后,让每个线程自行调用
list.iterator()获取专属副本 - 若需分片处理(如 4 个线程各处理 1/4),可用
subList()切分再各自迭代,互不干扰 - 切忌把一个迭代器对象传给多个线程,或在工具方法中意外复用
用 AtomicInteger 替代游标手动索引
放弃迭代器,转为原子索引协调访问:
立即学习“Java免费学习笔记(深入)”;
- 声明
AtomicInteger cursor = new AtomicInteger(0) - 每个线程循环调用
cursor.getAndIncrement()获取唯一下标 - 用该下标从线程安全集合(如
CopyOnWriteArrayList)中取元素 - 需自行判断越界,但逻辑清晰、无状态竞争、无锁开销
提前切分数据,彻底隔离遍历
最稳妥、性能最高的方式,适用于静态或极少写入的数据:
- 主线程将原始集合按线程数拆成 N 个互斥子列表(可用 Guava 的
Lists.partition()) - 每个子列表交给一个线程,线程内用普通
Iterator遍历,完全无共享、无同步、无异常风险 - 吞吐高,适合批量处理、ETL、离线计算等场景

















