java 集合并发操作出现的异常ConcurrentModificationException

 更新时间:2009年06月04日 02:31:12   作者:  
Map在遍历时候通常 现获得其键值的集合Set,然后用迭代器Iterator来对Map进行遍历。
如Java中的容器Map:
for(Person person : pList){
if(person.getGender()==Gender.MALE){
pList.remove(person); //不能在遍历期间进行 remove这个操作
}
}
Map在遍历时候通常 现获得其键值的集合Set,然后用迭代器Iterator来对Map进行遍历。
注意在遍历的过程中,只能对Map中的元素进行相应的处理,不能把Map元素增加或者把Map元素减少,也就是说,不能改变Map的size大小,就会出现异常(不能在遍历过程中修改删除或者增加map中的元素)
报出的异常为 java.util.ConcurrentModificationException 异常
public class ConcurrentModificationExceptionextends RuntimeException
当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。
例如,某个线程在 Collection 上进行迭代时,通常不允许另一个线性修改该 Collection。通常在这些情况下,迭代的结果是不明确的。如果检测到这种行为,一些迭代器实现(包括 JRE 提供的所有通用 collection 实现)可能选择抛出此异常。执行该操作的迭代器称为快速失败迭代器,因为迭代器很快就完全失败,而不会冒着在将来某个时间任意发生不确定行为的风险。
注意,此异常不会始终指出对象已经由不同 线程并发修改。如果单线程发出违反对象协定的方法调用序列,则该对象可能抛出此异常。例如,如果线程使用快速失败迭代器在 collection 上迭代时直接修改该 collection,则迭代器将抛出此异常。
注意,迭代器的快速失败行为无法得到保证,因为一般来说,不可能对是否出现不同步并发修改做出任何硬性保证。快速失败操作会尽最大努力抛出 ConcurrentModificationException。因此,为提高此类操作的正确性而编写一个依赖于此异常的程序是错误的做法,正确做法是:ConcurrentModificationException 应该仅用于检测 bug。
当使用 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.

相关文章

  • Java设计模式之java策略模式详解

    Java设计模式之java策略模式详解

    这篇文章主要介绍了Java经典设计模式之策略模式,简单说明了策略模式的概念、原理并结合实例形式分析了java策略模式的具有用法与相关注意事项,需要的朋友可以参考下
    2021-09-09
  • SpringBoot操作Jedis案例代码

    SpringBoot操作Jedis案例代码

    这篇文章主要介绍了SpringBoot操作Jedis案例代码,代码部分包括pom依赖、配置相关参数、JedisPool的设置,代码简单易懂对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-08-08
  • springboot启动mongoDB报错之禁用mongoDB自动配置问题

    springboot启动mongoDB报错之禁用mongoDB自动配置问题

    这篇文章主要介绍了springboot启动mongoDB报错之禁用mongoDB自动配置问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05
  • Java读取JSON文件并将其中元素转为JSON对象输出的方式

    Java读取JSON文件并将其中元素转为JSON对象输出的方式

    这篇文章主要介绍了Java读取JSON文件并将其中元素转为JSON对象输出的方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-10-10
  • 通过Java添加Word文本框过程详解

    通过Java添加Word文本框过程详解

    这篇文章主要介绍了通过Java添加Word文本框过程详解,在Word中,文本框是指一种可移动、可调节大小的文字或图形容器。我们可以向文本框中添加文字、图片、表格等对象,下面,将通过Java编程来实现添加以上对象到Word文本框,需要的朋友可以参考下
    2019-07-07
  • myeclipse10配置tomcat教程详解

    myeclipse10配置tomcat教程详解

    这篇文章主要为大家详细介绍了myeclipse10配置tomcat的教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-07-07
  • Spring MVC返回JSON视图的六种方式及对比详解

    Spring MVC返回JSON视图的六种方式及对比详解

    在 Spring MVC 中返回 JSON 格式的数据是一种常见的需求,特别是在构建 RESTful Web 服务时,可以通过以下几种方式实现控制器方法返回 JSON 数据,需要的朋友可以参考下
    2025-08-08
  • Mybatis操作Clickhouse数组的最佳实践分享

    Mybatis操作Clickhouse数组的最佳实践分享

    ClickHouse 的 Array(T) 数据类型支持任意有效数据类型作为元素,包括基本类型、嵌套数组和可空类型,本文给大家分享了Mybatis操作Clickhouse数组的最佳实践,需要的朋友可以参考下
    2025-09-09
  • SpringBoot整合RabbitMQ的5种模式实战

    SpringBoot整合RabbitMQ的5种模式实战

    本文主要介绍了SpringBoot整合RabbitMQ的5种模式实战,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • J2EE Servlet上传文件到服务器并相应显示功能的实现代码

    J2EE Servlet上传文件到服务器并相应显示功能的实现代码

    这篇文章主要介绍了J2EE Servlet上传文件到服务器,并相应显示,在文中上传方式使用的是post不能使用get,具体实例代码大家参考下本文
    2018-07-07

最新评论