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

(转)HashMap出现 java.util.ConcurrentModificationException

    博客分类:
  • JAVA
 
阅读更多
转载: http://www.oschina.net/question/1092_2544
Iterator<Integer> keys = gradeMap.keySet().iterator();
        while(keys.hasNext()){
            Integer i = keys.next();
            if(!gradesIds.contains(i)){
//                keys.remove();
                gradeMap.remove(i);
            }
        }


调用HashMap的reomve方法时会出现 java.util.ConcurrentModificationException 。
解决方法就是先用Iterator的方法remove,然后再调用HashMap的remove方法!!即代码如下:

Iterator<Integer> keys = gradeMap.keySet().iterator();
        while(keys.hasNext()){
            Integer i = keys.next();
            if(!gradesIds.contains(i)){
                keys.remove();
                gradeMap.remove(i);
            }
        }


or use the other way:
List sessionKeyList = new ArrayList();
                // one iterator
		synchronized (jmsQueueSessionsMap) {
			Iterator iterator = jmsQueueSessionsMap.keySet().iterator();

			while (iterator.hasNext()) {
				Object sessionKey = iterator.next();

				sessionKeyList.add(sessionKey);
			}
		}
                // the other iterator
		for (int i = 0; i < sessionKeyList.size(); i++) {
			Object sessionKey = sessionKeyList.get(i);
			JmsQueueSession jmsQueueSession = (JmsQueueSession) jmsQueueSessionsMap
					.remove(sessionKey);

			if (jmsQueueSession != null) {
				jmsQueueSession.destroy();
				jmsQueueSession = null;
			}
		}

		sessionKeyList.clear();


产生此问题的原因

引用于网络:
       当使用 fail-fast iterator 对 Collection 或 Map 进行迭代操作过程中尝试直接修改 Collection / Map 的内容时,即使是在单线程下运行, java.util.ConcurrentModificationException 异常也将被抛出。

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

所以 Iterator 在工作的时候是不允许被迭代的对象被改变的。但你可以使用 Iterator 本身的方法 remove() 来删除对象, Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。

有意思的是如果你的 Collection / Map 对象实际只有一个元素的时候, ConcurrentModificationException 异常并不会被抛出。这也就是为什么在 javadoc 里面指出: it would be wrong to write a program that depended on this exception for its correctness: ConcurrentModificationException should be used only to detect bugs.

附:来自ibm developerworks上对java.util.concurrent包的说明片段:
      java.util 包中的集合类都返回 fail-fast 迭代器,这意味着它们假设线程在集合内容中进行迭代时,集合不会更改它的内容。如果 fail-fast 迭代器检测到在迭代过程中进行了更改操作,那么它会抛出 ConcurrentModificationException ,这是不可控异常。
      在迭代过程中不更改集合的要求通常会对许多并发应用程序造成不便。相反,比较好的是它允许并发修改并确保迭代器只要进行合理操作,就可以提供集合的一致视图,如 java.util.concurrent 集合类中的迭代器所做的那样。
     java.util.concurrent 集合返回的迭代器称为弱一致的(weakly consistent) 迭代器。对于这些类,如果元素自从迭代开始已经删除,且尚未由 next() 方法返回,那么它将不返回到调用者。如果元素自迭代开始已经添加,那么它可能返回调用者,也可能不返回。在一次迭代中,无论如何更改底层集合,元素不会被 返回两次。

高并发,并且你的map是经常修改的,千万不要用HashMap,会把这个线常卡死的要用ConcurrentHashMap(不知是否正确,有时间得验证下)
分享到:
评论

相关推荐

    java.util.ConcurrentModificationException 解决方法

    java.util.ConcurrentModificationException 解决方法 ... at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793) at java.util.HashMap$KeyIterator.next(HashMap.java:828) 例如以下程序(转

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

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

    Java语言的Util类详细介绍

    Java语言的Util类详细介绍 Java语言的Util类是Java开发中非常重要的一部分,它提供了一系列的类来实现基本的数据结构,如线性表、链表等。这些类均在java.util包中。 Collection接口是Java中最基本的集合接口,一...

    Java多线程安全集合

    Java的`java.util.concurrent`包提供了更为高效且专门设计用于并发操作的集合。比如: - `ConcurrentHashMap`:线程安全的哈希映射,比`synchronized Map`性能更好,因为它允许不同部分独立加锁,减少了锁竞争。 ...

    多线程中使用Java集合类.doc

    3. 使用`java.util.concurrent.ConcurrentHashMap`代替HashMap,它在并发环境下提供高效且线程安全的访问和修改。 4. 如果需要更复杂的并发控制,可以使用`java.util.concurrent.locks`包下的Lock接口及其实现,如...

    concurrent.rar

    还有`java.util.concurrent`包中的`ConcurrentHashMap`,它是线程安全的哈希映射,比`synchronized` HashMap性能更好。 2. **并发容器**:包括`BlockingQueue`(阻塞队列)如`ArrayBlockingQueue`, `...

    Java中的几个HashMapConcurrentHash

    `HashMap`是Java集合框架的一部分,位于`java.util`包下,它提供了快速的插入、删除和查找操作,平均时间复杂度为O(1)。`HashMap`是非线程安全的,也就是说,当多个线程同时访问并修改`HashMap`时,可能会导致数据不...

    高级程序员必会的HashMap的线程安全问题,适用于0~2年的.7z

    1. **使用线程安全的类**:Java提供了一些线程安全的Map实现,如`java.util.concurrent.ConcurrentHashMap`。ConcurrentHashMap使用分段锁技术,使得在保证线程安全的同时,提供了较好的并发性能。 2. **同步访问**...

    java7-8中的 HashMap和ConcurrentHashMap全解析

    在Java编程语言中,`HashMap`和`ConcurrentHashMap`是两种非常重要的数据结构,它们都属于`java.util`包,用于存储键值对。本文将深入解析这两个类在Java 7和8版本中的实现原理、特点以及使用场景。 首先,`HashMap...

    Java HashMap 如何正确遍历并删除元素的方法小结

    这段代码将抛出 `java.util.ConcurrentModificationException` 异常,因为在遍历 HashMap 的元素过程中删除了当前所在元素,下一个待访问的元素的指针也由此丢失了。 2. 正确的删除方法 正确的删除方法是使用迭代...

    java哈希表(1).zip

    在Java中,`HashMap`类就是对哈希表的一种实现,它是`java.util`包的一部分。`HashMap`提供了线程非同步的快速存储和检索,其内部使用了数组和链表(或红黑树)来存储数据。 1. **哈希函数**:哈希函数是哈希表的...

    Java程序员容易犯的10个错误

    当使用`Arrays.asList()`方法将数组转换为列表时,返回的是`java.util.Arrays.ArrayList`,这是一个内部静态类,不支持添加或删除元素。如果需要一个可变的ArrayList,应使用构造函数创建新的ArrayList实例,如: ...

    java实现遍历Map的方法

    import java.util.HashMap; import java.util.Iterator; import java.util.Map; public class TestMap { public static void main(String[] args) { Map, Integer&gt; map = new HashMap(); map.put(1, 1); map....

    【面试普通人VS高手系列】Fail-safe机制与Fail-fast机制分别有什么作用.doc

    这种机制下的集合容器,例如HashMap和ArrayList等,都是java.util包下的集合类,它们在遍历时直接访问集合内容,因此在遍历过程中对集合数据做变更时,就会发生Fail-fast。 Fail-safe机制是一种失败安全机制,在...

    hashmap-thread-test:测试 Java HashMap 是否是线程安全的

    在Java编程语言中,`HashMap`是一个非常常用的数据结构,它提供了一种高效的方式来存储和检索键值对。然而,`HashMap`并非线程安全,这意味着在多线程环境中直接使用`HashMap`可能会导致数据不一致、并发问题,甚至...

    java-collection-all-in-one.pdf

    在java.util包和java.util.concurrent包中,Java集合框架被细分为两大类:基础集合类和并发集合类。基础集合类主要用于单线程环境中,而并发集合类则专为多线程环境设计,提供了线程安全的集合操作。 Java集合框架...

    Java 10道中级面试题.docx

    - Java BlockingQueue 是并发编程的重要工具,属于 `java.util.concurrent` 包。它支持阻塞的插入和移除操作,等待元素可用或空间可用。这对于实现生产者消费者模式等多线程通信场景非常有用。 4. **...

    Java程序员们最常犯的10个错误.docx

    然而,这返回的是一个内部类`java.util.Arrays.ArrayList`,它不支持添加元素。如果需要可变的`ArrayList`,应该使用构造函数来创建新的`ArrayList`,如: ```java ArrayList&lt;String&gt; arrayList = new ArrayList...

    集合框架面试题.pdf

    而java.util.concurrent包下的集合类则提供安全失败迭代器,它们在遍历时不会因为集合被修改而抛出异常,因为它们是基于集合的快照来实现的。 4. HashMap是一个用于存储键值对的集合。它基于哈希表的Map接口实现,...

Global site tag (gtag.js) - Google Analytics