ConcurrentModificationException(源码学习 Util包 集合)
来源:互联网 发布:arm linux gcc 4.3.2 编辑:程序博客网 时间:2024/06/05 05:50
ArrayList<String> list3=new ArrayList<String>();list3.add("1");list3.add("2");list3.add("3");Iterator i=list3.iterator();//for(Iterator i1=list3.iterator();i1.hasNext();){if(i.hasNext()){String s=(String) i.next();if(s=="1"){list3.remove(s);}}System.out.println(Arrays.toString(list3.toArray()));
上面这样是不不会报错ConcurrentModificationException
但是你用代码中for循环中的代码这种方式遍历就会出错
所以,产生ConcurrentModificationException的原因就是:
执行remove(Object o)方法之后,源码(modCount和expectedModCount)
如下面所示:
ArrayList:
public boolean remove(Object o) {if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);//看下面方法
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
/*
* Private remove method that skips bounds checking and does not
* return the value removed.
*/
private void fastRemove(int index) {
modCount++;//在调用此方法的时候modCount的值加1
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work
}
下面是AbstractList 实现了 List接口 extends Collections exrends Iterator
public E next() {
checkForComodification();
try {
E next = get(cursor);
lastRet = cursor++;
return next;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
final void checkForComodification() {
if (modCount != expectedModCount){
//因为在调用ArrayList remove方法的时候modCount 已经加1
throw new ConcurrentModificationException();//异常出现
}
}
不相等了。然后当代码执行到next()方法时,判断了checkForComodification(),发现两个数值不等,就抛出了该Exception。
要避免这个Exception,就应该使用remove()方法。
public void remove() {
if (lastRet == -1)
throw new IllegalStateException();
checkForComodification();
try {
AbstractList.this.remove(lastRet);
if (lastRet < cursor)
cursor--;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
}
这里我们就不看add(Object o)方法了,也是同样的原因,但没有对应的add()方法。一般嘛,就另建一个List了
下面是网上的其他解释,更能从本质上解释原因:
Iterator 是工作在一个独立的线程中,并且拥有一个 mutex 锁。 Iterator 被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以按照 fail-fast 原则 Iterator 会马上抛出 java.util.ConcurrentModificationException 异常。
所以 Iterator 在工作的时候是不允许被迭代的对象被改变的。但你可以使用 Iterator 本身的方法 remove() 来删除对象, Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。
- ConcurrentModificationException(源码学习 Util包 集合)
- 深入分析集合并发修改异常(源码分析)java.util.ConcurrentModificationException
- 集合遍历 java.util.ConcurrentModificationException
- 集合框架(Util包)
- Java.util.concurrent包学习(三)同步集合
- java.util包的集合框架学习
- java.util.ConcurrentModificationException 集合remove异常
- 修改集合抛出java.util.ConcurrentModificationException
- java.util.ConcurrentModificationException 与集合删除
- java.lang.UnsupportedOperationException(源码学习 Util包 Arrays)
- java util包学习(4) Arrays 源码分析
- java util包学习(5) Vector 源码分析
- java util包学习(6) LinkedLIst 源码分析
- java util包学习(7)Set 源码分析
- java util包学习(8)Map源码分析
- java util包学习(9)HashMap源码分析
- JAVA集合中删除元素时的java.util.ConcurrentModificationException
- 集合删除对象,报错java.util.ConcurrentModificationException
- SQLServer : EXEC和sp_executesql的区别
- JAVA动态代理--使用JAVA API实现JAVA动态代理
- 菜鸟小技巧:如何在网上隐藏自己的IP地址(1)
- XML学习笔记(一)
- shell 函数的返回值和退出状态
- ConcurrentModificationException(源码学习 Util包 集合)
- arch/arm/include/asm/io.h
- 无法获得锁 /var/lib/dpkg/lock - open (11: Resource temporarily unavailable) 解决办法
- live archive 5984 - Save the Students!
- C语言----函数和应用
- 使用 Crash 工具分析 Linux dump 文件
- 打开Word并插入图片
- http协议详解
- 中国制造VS国际品牌 耳熟能详游戏引擎比拼