首先,上单线程版的。
import java.util.ArrayList;
import java.util.Iterator;
public class ConcurrentModification {
public static void main(String[] args) {
ArrayList list=new ArrayList();
for(int i=0;i<10;i++)
{
list.add(i);
}
Iterator it=list.iterator();
while(it.hasNext())
{
System.out.println(it.next());
list.remove(it.next());
}
}
}
java源码解析:
AbstractList$Itr
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
这个方法被遍历系列调用(next、previous),也会被修改系列方法调用(add、remove、set)。
modCount为实际修改次数,expectedModCount为期望修改次数。如果实际修改次数不等于期望修改次数的话,就会抛出如上异常。
那么我们看看next()方法:
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;
}
而fastRemove()方法代码如下:
/*
* Private remove method that skips bounds checking and does not
* return the value removed.
*/
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work
}
很显然,只修改了modCount,但是expectedModCount并未变,那么到下一个next()方法时就会出现不一致,抛出异常。
至于避免的方法有两种:
Collections.synchronizedList()方法
CopyOnWriteArrayList