`

java.util.ConcurrentModificationException出现原因及解决方案

阅读更多
public void setReparation( Reparation reparation ) {  
    for (Iterator it = this.reparations.iterator();it.hasNext();)  {    //reparations为Collection  
         Reparation repa = (Reparation)it.next();  
         if (repa.getId() == reparation.getId()){  
             this.reparations.remove(repa);  
             this.reparations.add(reparation);  
         }  
     }  
}  

执行以上代码时,编译器会报ConcurrentModificationException.
原因是:
    当使用 fail-fast iterator 对 Collection 或 Map 进行迭代操作过程中尝试直接修改 Collection / Map 的内容时,即使是在单线程下运行,ava.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.

解决方案:
1.如果在迭代过程中,需要往Collection 或 Map中插入新的元素时,不要用他们的API提供的方法直接插入删除,可以考虑通过使用他们的迭代器的新增,删除方法来操作元素.
2.不要用迭代器循环,而是直接将Collection 或 Map转换成数组来循环即可.
分享到:
评论

相关推荐

    Java多线程安全集合

    虽然提供了基本的线程安全性,但它们不是高度优化的并发解决方案,因为所有操作都需要全局锁定,可能导致性能瓶颈。 2. 并发集合(Concurrent Collections): Java的`java.util.concurrent`包提供了更为高效且...

    Java 实例 - 只读集合源代码+详细指导教程.zip

    在Java编程中,只读集合(Read-Only Collection)是一种不允许进行修改的集合类型,它提供了安全的数据访问...详细指导将涵盖各种使用场景、最佳实践以及可能遇到的问题和解决方案,帮助你成为一名更优秀的Java开发者。

    Java并发编程的艺术.zip

    - **并发容器**:如`ConcurrentHashMap`、`CopyOnWriteArrayList`、`ConcurrentLinkedQueue`等,为并发访问提供了线程安全的解决方案。 - **阻塞队列**:`BlockingQueue`接口,实现生产者消费者模型,如`...

    Java 常见问题解决集合.docx

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

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

    如果能查看博客的具体内容,将有助于提供更具体的解决方案。此外,`CoffeeSystem`可能是一个相关的系统或者类库,但没有足够的信息来进一步分析其与`iterator()`问题的联系。 为了更好地调试和解决问题,你可以按照...

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

    本篇将深入探讨HashMap的线程安全问题,并提供相关的解决方案。 首先,我们需要了解HashMap在多线程环境下可能出现的问题: 1. **并发修改异常(ConcurrentModificationException)**:当多个线程同时修改HashMap...

    ConcurrentHashMap:今天在看Spring源码的时候发现了一个并发安全的hashmap,自己就手写实现了一下

    `ConcurrentHashMap`是Java集合框架中的一个关键成员,它在`java.util.concurrent`包下,为并发操作提供了一种高效且线程安全的解决方案。与传统的`synchronized` `HashMap`相比,`ConcurrentHashMap`采用了分段锁的...

    DataStructures:Java中的哈希表

    这个类位于Java的集合框架中,为程序员提供了灵活且性能优异的键值对存储解决方案。 **哈希表的工作原理** 哈希表基于数组和链表的组合实现。当插入一个新的键值对时,哈希函数会计算键的哈希码,然后根据这个哈希...

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

    ### 解决方案 1. **Collections.synchronizedMap()**:可以使用`Collections.synchronizedMap()`静态方法将`HashMap`包装成线程安全的`SynchronizedMap`。但请注意,尽管这个方法可以确保并发修改的安全,但仍然...

    超级有影响力霸气的Java面试题大全文档

     GC是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收...

    高并发常见面试题(深入底层).docx

    当多个线程同时调用`add`方法时,可能会抛出`java.util.ConcurrentModificationException`异常。 **4.2 解决方案** - 使用`Vector`类代替`ArrayList`,因为`Vector`的所有公共方法都进行了同步处理,但这种方法降低...

    DATASTRUCTURES-LINKEDLIST

    在Java编程语言中,链表主要体现在`LinkedList`类中,它是Java集合框架的一部分,位于`java.util`包下。 链表的基本组成部分是节点(Node),每个节点包含数据元素和指向下一个节点的引用。在Java的`LinkedList`中...

Global site tag (gtag.js) - Google Analytics