引发ConcurrentModificationException的代码:
package test; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class ConcurrentModificationExceptionDemo { public static void main(String[] args) { List<String> list = new ArrayList<String>(); list.add("map"); list.add("key"); list.add("jmey"); Iterator<String> iterator = list.iterator(); while(iterator.hasNext()){ list.add("bool"); String val = iterator.next(); System.out.println("values is:"+val); } } }
创建集合迭代器时,返回Itr对象:
public Iterator<E> iterator() { return new Itr(); }
调用迭代器的next()或remove()方法
private class Itr implements Iterator<E> { int cursor; // index of next element to return int lastRet = -1; // index of last element returned; -1 if no such int expectedModCount = modCount; public boolean hasNext() { return cursor != size; } @SuppressWarnings("unchecked") public E next() { checkForComodification(); int i = cursor; if (i >= size) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); cursor = i + 1; return (E) elementData[lastRet = i]; } 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(); } } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } }
从代码中看出会首先执行checkForComodification()方法,该方法如下:
final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); }
首先会检查modCount和expectedModCount是否相等,如果不等则抛出ConcurrentModificationException,而expectedModCount在创建
迭代器的时候由modCount赋值,在代码中可看到。而modCount则是记录集合改动的元素个数,在集合中元素变动的时候,该值会相应的
发生改动。
private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); }
在上述迭代器遍历集合元素时先执行了list.add("bool")此时modCount变为4,而expectedModCount则为3(因集合添加了3个
元素后直接获取迭代器所以为3),因此在后续执行next()检查expectedModCount不等于modCount,从而抛出
ConcurrentModificationException,分析后得知:迭代器在遍历集合元素时,改变集合元素会引发该异常。此情况在多线并发读写同
一个ArrayList也可能引发该异常.