`
lc_koven
  • 浏览: 353318 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

ConcurrentModificationException异常的原因及解决

阅读更多
    今天在对map进行遍历的程序中发现抛出ConcurrentModificationException 异常:

    一个线程中:
Map<byte[],byte[]> map = new ConcurrentHashMap<byte[],byte[]>();
			while((row = results.next()) != null){
				map.clear();
				...
				queue.put(map);
			}


    另一个线程中:

while(queue.size() > 0){
				line = queue.poll();
				if(line == null)
					continue;
				Iterator<Map.Entry<byte[],byte[]>> it = line.entrySet().iterator();
				while(it.hasNext()){
					...
				}
			}

    即使读写线程分别只用一个,也会抛出该异常。

    原因是Iterator是工作在一个独立的线程中,并且拥有一个 mutex 锁。 Iterator 被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以按照 fail-fast 原则 Iterator 会马上抛出 java.util.ConcurrentModificationException 异常。
(http://www.iteye.com/topic/124788)

    所以当读线程中执行了map.clear()后,写线程的Iterator指向的原始对象就变化了,导致抛出异常。修改读线程代码为:
Map<byte[],byte[]> map;
			while((row = results.next()) != null){
				map = new ConcurrentHashMap<byte[],byte[]>();
				...
				queue.put(map);
			}


    问题解决。
0
3
分享到:
评论
2 楼 lc_koven 2011-09-10  
nowopen 写道
ConcurrentHashMap应该不会有ConcurrentModificationException异常,是不是其他原因?

Set<Entry<K, V>> java.util.concurrent.ConcurrentHashMap.entrySet()Returns a Set view of the mappings contained in this map. The set is backed by the map, so changes to the map are reflected in the set, and vice-versa. The set supports element removal, which removes the corresponding mapping from the map, via the Iterator.remove, Set.remove, removeAll, retainAll, and clear operations. It does not support the add or addAll operations.

The view's iterator is a "weakly consistent" iterator that will never throw ConcurrentModificationException, and guarantees to traverse elements as they existed upon construction of the iterator, and may (but is not guaranteed to) reflect any modifications subsequent to construction.

恩,大师,ConcurrentModificationException 是从List中抛出的,这里就是queue。当map执行clear后,再去访问原来put到queue中的元素后就出错了。我代码可能没有引用完
1 楼 nowopen 2011-09-09  
ConcurrentHashMap应该不会有ConcurrentModificationException异常,是不是其他原因?

Set<Entry<K, V>> java.util.concurrent.ConcurrentHashMap.entrySet()Returns a Set view of the mappings contained in this map. The set is backed by the map, so changes to the map are reflected in the set, and vice-versa. The set supports element removal, which removes the corresponding mapping from the map, via the Iterator.remove, Set.remove, removeAll, retainAll, and clear operations. It does not support the add or addAll operations.

The view's iterator is a "weakly consistent" iterator that will never throw ConcurrentModificationException, and guarantees to traverse elements as they existed upon construction of the iterator, and may (but is not guaranteed to) reflect any modifications subsequent to construction.

相关推荐

    遍历并批量删除容器中元素出现ConcurrentModificationException原因及处置

    下面详细解析一下这个问题的原因和解决策略: 1. **原因分析**: - 当你使用`for-each`循环(增强for循环)遍历集合时,实际上底层是通过迭代器实现的。但是,如果你在循环内部直接修改集合(比如删除元素),而...

    出现java.util.ConcurrentModificationException 问题及解决办法

    在Java编程中,`java.util.ConcurrentModificationException` 是一个常见的运行时异常,通常发生在尝试并发修改集合时。这个异常的产生是由于集合类(如HashMap)的非线程安全特性,当你在一个线程中使用迭代器遍历...

    java.util.ConcurrentModificationException 解决方法

    `java.util.ConcurrentModificationException` 是一个在 Java 中常见的运行时异常,它通常发生在多线程环境中,当一个线程正在遍历一个集合(如 `ArrayList`, `HashMap` 等),而另一个线程同时尝试修改这个集合时。...

    Java 常见问题解决集合.docx

    ### Java常见问题及解决方案 #### 一、编译错误 **1.1 问题:** "cannot find symbol" **解决:** 这个错误提示通常意味着Java编译器未能找到指定的类、方法或变量。要解决这个问题,需要进行以下几个步骤的检查: ...

    HashMap和List遍历方法及如何遍历删除元素总结

    原因在于,在增强for循环中,实际上是使用Iterator来遍历List,而Iterator并不能检测到List的变化,从而导致异常。 解决方法 要解决List遍历删除元素的问题,可以使用Iterator来遍历List,并使用Iterator的remove...

    forEach中为什么不能删除元素解决方案.pdf

    需要注意的是,代码示例在本问题描述中由于OCR扫描的原因无法提供,所以在具体实现这些解决方案时,开发者应该参考Java官方文档或相应的编程指南来确保正确和有效的代码实现。 通过这些方法,可以有效解决在使用`...

    好几天解决不了的问题源代码

    例如,可能是在遍历`Map`时没有正确地处理`Iterator`,导致并发修改异常(`ConcurrentModificationException`);或者是在查找或插入键值对时遇到了键的唯一性问题;也可能是性能问题,比如在大量数据上使用了不适合...

    java常见错误集合以及描述

    ### Java常见错误集合以及...通过了解这些异常的原因及解决方案,可以帮助开发者更好地处理异常情况,提高程序的健壮性和稳定性。此外,合理的异常处理策略也是提高开发效率的关键。希望本文能对Java开发者有所帮助。

    java环境报错大全下载地址

    10. **ConcurrentModificationException**:在多线程环境下,当一个线程正在修改集合,而另一个线程尝试遍历同一集合时,会抛出此异常。使用并发控制或使用不可变集合来避免。 以上仅是Java环境报错中的一部分,...

    java集合代码

    在实际开发中,理解这些异常及其原因可以帮助我们编写更健壮的代码。为了正确处理这些异常,我们可以使用try-catch块,或者使用Java 7引入的`try-with-resources`语句来确保资源的正确关闭。此外,良好的编程习惯和...

    关于方法iterator()找不着的问题~~~~~

    当你遇到“方法iterator()找不着的问题”时,这通常意味着你在尝试使用`iterator()`时遇到了错误,可能是由于以下几个原因: 1. **类库不兼容**: 如果你正在使用的类库版本不支持`iterator()`方法,比如你引用了...

    android 错误 整理 来自网上

    以上仅列举了部分Android开发中常见的错误类型,理解它们的原因和解决方法是提升开发效率和应用质量的关键。在实践中,通过日志调试、使用Android Studio提供的分析工具,以及学习更多Android SDK文档,可以更好地...

    java面试笔记整理,包含java,redis,kafka等

    - **面向过程:** 侧重于定义一系列的过程来解决问题,更注重算法的设计。 #### 七、面向对象的特性 - **封装:** 将数据和行为绑定在一起,隐藏对象的内部状态。 - **继承:** 允许子类继承父类的属性和方法。 - **...

    Java开发常见问题总结.docx

    - 在遍历集合时对其进行修改可能会导致`ConcurrentModificationException`异常。为了安全起见,在循环外部进行修改操作。 #### 四、异常处理 1. **合理捕获并处理异常** - 不应该忽视任何异常,而是应该适当地...

    SJSU-CS160-SurpriseError

    通过查看项目源代码,我们可以更具体地定位问题所在,比如查看日志文件、异常堆栈跟踪等,以找出引发"SurpriseError"的具体原因。 为了提高代码质量和防止未来出现类似的“惊喜”错误,开发者应该遵循良好的编程...

    day04集合.pdf

    在使用迭代器遍历集合的过程中,如果通过集合对象修改了集合中的元素(如添加、删除等操作),会导致迭代器获取元素时判断预期修改值和实际修改值不一致,从而抛出`ConcurrentModificationException`异常。...

    ArrayList.docx

    在多线程环境中,如果对正在遍历的集合进行修改,会立即抛出`ConcurrentModificationException`异常。 2. **安全失败**: - `java.util.concurrent`包下的类(如`CopyOnWriteArrayList`)采用安全失败机制。遍历时...

    【Java面试题】List如何一边遍历,一边删除?

    这样做的原因是`iterator.remove()`会更新迭代器的内部状态,使得`modCount`和`expectedModCount`保持一致,避免抛出异常。 3. **使用for循环正序遍历** 另一种方法是使用传统的for循环,通过索引来访问和删除...

    阿里巴巴Java开发手册(嵩山版).pdf

    - **操作风险**:在遍历集合时修改集合本身会导致`ConcurrentModificationException`异常。 - **应对策略**:若需要在遍历过程中删除或添加元素,推荐使用迭代器提供的`remove`方法,或者先复制集合再进行操作。 ##...

    藏经阁-Java开发手册(泰山版)灵魂13问-117.pdf

    对于ArrayList而言,直接在foreach循环中进行元素的remove或add操作可能会导致`ConcurrentModificationException`,因为这违反了迭代器的协定。应使用`Iterator`进行这类操作。 7. **避免直接使用日志系统的API**...

Global site tag (gtag.js) - Google Analytics