Java ConcurrentModificationException
Java集合遍历中ConcurrentModificationException解决办法
该异常出现的一般原因:不允许的并发修改操作
我们查看JAVA API的时候就可以了解到,ConcurrentModificationException是继承了RuntimeException的一个异常,所以它是一个运行时的异常类。通常发生在并发操作’时错误的读写导致的异常错误。这个异常可以通过方法抛出,当探测到对一个对象进行并发修改,然而这个并发修改操作不被允许的时候。
比如说,当一个集合对象是不允许多个线程同时对其进行修改的,当有一个迭代器正在迭代遍历这个集合的时候,如果还有额外的迭代器进行修改操作,这个时候就会报ConcurrentModificationException这个异常。在JDK1.2以及1.2之后就新增了这个异常,至于具体的原因机制可以查看JDK的API文档。点击这里查看1.7版本的JDK。
该异常出现的一般情况:在遍历中对集合中的对象元素进行修改操作
注意:使用迭代器进行遍历,只能通过迭代器进行删除操作,否则则报这个异常,如下:
示例代码1:
@Test
public void testCreateConcurrentModificationException() {
try {
ArrayList<String> testList = new ArrayList<String>();
testList.add(new String("One"));
testList.add(new String("Two"));
testList.add(new String("Three"));
Iterator<String> iter1 = testList.iterator();
for (String str = ""; iter1.hasNext();) {
str = iter1.next();
testList.remove(0);
}
} catch (ConcurrentModificationException e) {
e.printStackTrace();
}
}
此时,绝对爆出异常:
java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
...
该异常的原理解析:遍历计数器的不均等导致
如示例代码1所示,这里使用的是testList.remove(0);
,直接使用原集合对象进行删除操作,这样为什么不行呢,原因很简单,我们不妨看一下ArrayList的源码中的方法:
AbstractList 类的 hasNext()和 next()方法:
public boolean hasNext() {
return cursor != size();
}
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)
throw new ConcurrentModificationException();
}
所以说,在使用迭代器的时候,next()中调用的checkForComodification(), 在remove方法中也调用了checkForComodification()当进行删除操作的时候,==modCount != expectedModCount,此时绝对会抛出应有这个异常。总而言之一句话,就是使用那个迭代器时会初始化一个迭代器,使用集合对象本身的add或者remove操作的时候也会在内部产生一个迭代器,当在迭代器遍历中使用集合对象删除的时候,里边的modCount会减少,而当使用迭代器的next()方法是,其检测到的modCount和期待的count已经不等了==,于是报出这个异常。
该异常的解决方法:在迭代器内部使用迭代器本身进行删除和修改操作
iterator.remove();
延伸:
集合的拷贝:Java集合中深复制与浅复制
笔者本人相关阅读:
在Github上的静态托管博客1:ALBOG
在Github上的静态托管博客2:Programming Sky
欢迎大家阅读本人博客,我是Anderson Lu
October 31, 2015 6:59 PM