集合中的Iterator抛出的ConcurrentModificationException源码分析

来源:互联网 发布:欧莱雅 曼秀雷敦 知乎 编辑:程序博客网 时间:2024/05/16 10:12

主题:ConcurrentModificationException的集合迭代器归属

1.正常抛出超出边界等异常


List<Integer> list;  //添加元素等  int i = list.size();  for (int n = 0; n < i; n++) {      if (list.get(n).equals(1)) {          list.remove(n);      }  }  //如果list.get(n)的n超出边界,抛出异常  


2.认识fail-fast的集合检测机制

“快速失败”也就是fail-fast,它是Java集合的一种错误检测机制。当多个线程对集合进行结构上的改变的操作时,有可能会产生fail-fast机制。记住是有可能,而不是一定。例如:假设存在两个线程(线程1、线程2),线程1通过Iterator在遍历集合A中的元素,在某个时候线程2修改了集合A的结构(是结构上面的修改,而不是简单的修改集合元素的内容),那么这个时候程序就会抛出 ConcurrentModificationException 异常,从而产生fail-fast机制。

一.ArrayList分析

里面的Itr迭代类检测是否在原来的list进行修改方法

Itr的成员变量
        int cursor;       // index of next element to return        int lastRet = -1; // index of last element returned; -1 if no such        int expectedModCount = modCount;//跟随迭代器


List的成员变量
       protected transient int modCount = 0;//remove等元素操作加1


//下面就是迭代器的快速失败的原理
final void checkForComodification() {            if (modCount != expectedModCount)                throw new ConcurrentModificationException();        }

所以要进行remove等操作,请使用迭代器的remove,请看Itr的remove源码

此时 Itr的expectedModCount改变,所以checkForComodification()不会抛出该异常,而且同步更新Itr和当前list的元素

public void remove() {            if (lastRet < 0)                throw new IllegalStateException();            checkForComodification();            try {                ArrayList.this.remove(lastRet);                cursor = lastRet;                lastRet = -1;                expectedModCount = modCount;            } catch (IndexOutOfBoundsException ex) {                throw new ConcurrentModificationException();            }        }

二.HashMap的Map集合

原理也是有这样的一个检测方法,是集合修改等操作,请到set集合中修改,比如:
        Iterator it = hs.keySet().iterator();        while (it.hasNext()) {            String str = (String) it.next();            System.out.println(hs);            it.remove();//修改的是set,同步更新到map集合        }




阅读全文
1 0
原创粉丝点击