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

2016-02-19 11:41 4 1 收藏

下面,图老师小编带您去了解一下java 集合并发操作出现的异常ConcurrentModificationException,生活就是不断的发现新事物,get新技能~

【 tulaoshi.com - 编程语言 】

如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.

来源:http://www.tulaoshi.com/n/20160219/1598253.html

延伸阅读
标签: Web开发
代码如下: package cn.lang.any.listener; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; public class AmpList implements ServletContextListener,HttpSessionListener,HttpSessionAttributeListener { private ServletContext application=null; public void contextInitialized(ServletContextEvent...
本文重在Java中异常机制的一些概念。写本文的目的在于方便我很长时间后若是忘了这些东西可以通过这片文章迅速回忆起来。 1. 异常机制 1.1 异常机制是指当程序出现错误后,程序如何处理。具体来说,异常机制提供了程序退出的安全通道。当出现错误后,程序执行的流程发生改变,程序的控制权转移到异常处理器。 1.2 ...
    偏头痛发作前多有先兆症状,其中以视觉先兆最多见,如突然眼花、闪光暗点、异彩甚至黑、视野缺损等。常从中心视野开始,逐渐向颞侧扩大蔓延,形成同向视野中的幻觉或偏盲,先兆症状一般持续半小时左右。有的先兆症状偶可表现为咽、舌、唇或偏侧肢体感觉异常、偏侧麻木、偏瘫、言语功能障碍,这些症状在视觉症状之后出...
1、不能在finally块中执行return,continue等语句,否则会把异常“吃掉”; 2、在try,catch中假如有return语句,则在执行return之前先执行finally块 请大家仔细看下面的例子: 以下是引用片段: public class TryTest {      public static void main(S...
Queue ------------ 1.ArrayDeque, (数组双端队列) 2.PriorityQueue, (优先级队列) 3.ConcurrentLinkedQueue, (基于链表的并发队列) 4.DelayQueue, (延期阻塞队列)(阻塞队列实现了BlockingQueue接口) 5.ArrayBlockingQueue, (基于数组的并发阻塞队列) 6.LinkedBlockingQueue, (基于链表的FIFO阻塞队列) 7.LinkedBlockin...

经验教程

996

收藏

44
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部