在java多线程环境中,iterator本身不具备线程安全性,直接并发使用会导致concurrentmodificationexception或数据不一致。安全使用的核心做法是:要么在遍历期间持有锁(如synchronized或reentrantlock),要么使用支持并发修改的迭代器实现(如copyonwritearraylist的iterator或concurrenthashmap的iterator)。具体选择取决于你对数据一致性的要求:强一致性需加锁,最终一致性可使用弱一致性迭代器。

synchronized块中如何安全遍历集合
在synchronized代码块内获取并遍历Iterator是保证线程安全的最基础方式。通过锁定集合对象本身,确保同一时刻只有一个线程能访问该集合的迭代状态,从而避免结构修改引发的异常。这种做法适用于读多写少且竞争不激烈的场景,但需注意锁粒度可能影响性能。

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class SynchronizedIteratorExample {
private final List<string> list = new ArrayList();
private final Object lock = new Object();
public void add(String item) {
synchronized (lock) {
list.add(item);
}
}
public void safeTraverse() {
synchronized (lock) {
Iterator<string> it = list.iterator();
while (it.hasNext()) {
String item = it.next();
System.out.println("Processing: " + item);
// 模拟处理逻辑
}
}
}
}</string></string>
上述代码中,add和safeTraverse方法均使用同一个lock对象进行同步。当多个线程调用safeTraverse时,它们必须等待前一个线程释放锁才能进入遍历阶段。这样即使其他线程在外部修改了list,只要修改操作也受同一把锁保护,遍历时就不会抛出ConcurrentModificationException。预期输出为按添加顺序打印所有元素,且每次遍历结果与当前列表状态一致。
ConcurrentHashMap的Iterator行为特点
ConcurrentHashMap提供的Iterator是弱一致的,它允许在遍历过程中反映部分或全部后续插入、删除或更新操作,但不会抛出ConcurrentModificationException。这种设计牺牲了强一致性以换取高并发性能,适用于对实时性要求不高但需要高吞吐的场景。注意,其Iterator不支持remove操作,且遍历顺序不保证与插入顺序一致。

import java.util.concurrent.ConcurrentHashMap;
import java.util.Map;
public class ConcurrentMapIteratorExample {
private final ConcurrentHashMap<string integer> map = new ConcurrentHashMap();
public void put(String key, int value) {
map.put(key, value);
}
public void weaklyConsistentTraverse() {
for (Map.Entry<string integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
// 注意:此处不能调用entry.remove(),否则抛UnsupportedOperationException
}
}
}</string></string>
在weaklyConsistentTraverse方法中,我们直接遍历map.entrySet()。由于ConcurrentHashMap的内部机制,即使另一个线程在遍历期间调用了put或remove,当前遍历仍会继续执行而不会中断。例如,若初始map包含{a=1, b=2},遍历过程中线程B插入c=3,则遍历可能看到a=1, b=2, c=3,也可能只看到a=1, b=2,这取决于内部分桶的扫描时机。这种行为是预期的,开发者不应依赖遍历期间的完整快照。预期输出为键值对的无序打印,且不会因并发修改而崩溃。
Iterator.remove()在并发环境中的限制
在并发集合如ConcurrentHashMap中,Iterator的remove()方法被明确禁止,调用会抛出UnsupportedOperationException。这是因为并发集合的内部结构不允许在迭代过程中安全地移除元素而不破坏一致性。若需在遍历中移除元素,应使用显式的并发控制策略,如先收集待移除键再批量删除,或使用ConcurrentLinkedQueue等支持remove操作的队列类型。对于普通List,若在synchronized块外尝试remove,同样会引发异常,因此必须确保remove操作也在锁保护下进行。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











