遇到 ConcurrentModificationException,怎么办?

本文探讨了在多线程环境下使用Iterator遍历并修改集合时遇到的ConcurrentModificationException异常。通过示例展示了如何在多线程及单线程环境中避免此异常的发生,并提供了几种有效的解决方案。
当线程用iterator的方法(iterator.next)循环一个collection的的时候,另外一个线程改变了这个collection,就会抛出ConcurrentModificationException。即使同步的collection类,比如 SnchronizedMap 或 SynchronizedList 也只是有条件的线程安全,这是因为所有单独的操作是线程安全的,但是依靠上别的操作结果的混合操作就可能出现线程问题。

Collection<String> myCollection = new ArrayList<String>(10);
myCollection.add("123");
myCollection.add("456");
myCollection.add("789");
for (Iterator it = myCollection.iterator(); it.hasNext();) {
String myObject = (String)it.next();
System.out.println(myObject);
if (someConditionIsTrue) {
myCollection.remove(myObject); //多线程时也会抛出 ConcurrentModificationException
}
}


解决的方法:
(1)多线程的时候:
1)你可以把你的 list 转换成数组用 list.toArray() 然后迭代这个数组,但当 list 很大的时候不推荐这样做。
2)你可以用 synchronized 块把整个 list 操作和迭代全部包裹起来,不过当你的程序是高度并发的时候这个方法会对程序的伸缩性有影响。
3)如果你用 JDK1.5 那么你可以用 ConcurrentHashMap 和 CopyOnWriteArrayList ,它们提供很好的伸缩性,用 ConcurrentHashMap.iterator() 迭代就不会抛出 ConcurrentModificationException。
(2)单线程的时候:


it.remove(); //因为it有一个 myCollection 的引用,所以用 Iterator "it" 可以移除当前的对象,以可以用上面第3个方法。

别用

myCollection.remove(myObject); //避免在 Iterator迭代的时候,这会抛出ConcurrentModificationException的。
### 关于ConcurrentModificationException的发生场景 `ConcurrentModificationException` 主要发生在集合操作中,尤其是在多线程环境或者单线程下不正确地修改集合时。然而,这种异常并不完全局限于集合操作[^1]。 #### 1. **集合操作中的典型场景** 当一个线程正在遍历某个集合(如 `ArrayList` 或 `HashMap`),而另一个线程或同一线程通过非迭代器方法修改了该集合的结构(增删元素),就会触发此异常。这是最常见的发生场景之一[^1]。 #### 2. **其他可能引发异常的情况** 虽然 `ConcurrentModificationException` 的主要关联对象是集合类,但在某些情况下,类似的机制也可能应用于其他数据结构或工具类: - **自定义数据结构** 如果开发者实现了一个类似于集合的数据结构,并在其内部实现了失败快速检测(fail-fast mechanism),那么在这种数据结构被并发访问并修改的情况下,也可能会抛出此类异常[^4]。 - **Stream API 中的操作** 在 Java 8 及更高版本中引入的 Stream API 提供了一种更简洁的方式来处理集合数据。如果在流管道中尝试对源集合进行结构性修改,则同样有可能遇到 `ConcurrentModificationException`[^3]。 ```java List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C")); list.stream().forEach(item -> { if ("B".equals(item)) { list.remove(item); // ConcurrentModificationException } }); ``` 在此代码片段中,尽管表面上是对流执行操作,但由于底层仍然依赖原始集合,因此会产生异常。 #### 3. **解决办法扩展至非集合领域** 对于非集合类但具有类似行为的对象,可以借鉴集合的安全解决方案: - 使用同步块来保护共享资源; - 利用线程安全的设计模式,例如读写锁; - 替换为支持高并发的替代品,就像在集合中推荐使用的 `ConcurrentHashMap` 和 `CopyOnWriteArrayList` 等。 综上所述,尽管 `ConcurrentModificationException` 最常出现在集合上下文中,但从原理上看,任何具备 fail-fast 特性的组件都可能存在相似的风险。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值