先看怎么发生
List<Integer> list=new ArrayList<>();
for(int i=0;i<10;i++){
list.add(i);
}
Iterator<Integer> it=list.iterator();
while(it.hasNext()){
Integer str=it.next();
if(str==5)
list.remove(str);//不通过it.remove()方法删除,而是通过list.remove()方法删除元素
}
这段代码,就会发生java.util.ConcurrentModificationException异常 一下看看实现: 先看 AbstractList 类有这样一个变量
/**
* The number of times this list has been <i>structurally modified</i>.
* Structural modifications are those that change the size of the
* list, or otherwise perturb it in such a fashion that iterations in
* progress may yield incorrect results.
* 他代表list被修改的次数(一般指 add,remove 次数。某个元素重赋值,一般不计数 )
* <p>This field is used by the iterator and list iterator implementation
* returned by the {@code iterator} and {@code listIterator} methods.
* If the value of this field changes unexpectedly, the iterator (or list
* iterator) will throw a {@code ConcurrentModificationException} in
* response to the {@code next}, {@code remove}, {@code previous},
* {@code set} or {@code add} operations. This provides
* <i>fail-fast</i> behavior, rather than non-deterministic behavior in
* the face of concurrent modification during iteration.
* 这个变量,一般在是 iterator , list iterator 实现时用到的,并且在他们的 next,remove,add,previous 等方法中,会利用它决定是否抛出ConcurrentModificationException异常。
* <p><b>Use of this field by subclasses is optional.</b> If a subclass
* wishes to provide fail-fast iterators (and list iterators), then it
* merely has to increment this field in its {@code add(int, E)} and
* {@code remove(int)} methods (and any other methods that it overrides
* that result in structural modifications to the list). A single call to
* {@code add(int, E)} or {@code remove(int)} must add no more than
* one to this field, or the iterators (and list iterators) will throw
* bogus {@code ConcurrentModificationExceptions}. If an implementation
* does not wish to provide fail-fast iterators, this field may be
* ignored.
* 也可以在子类中利用这个字段,提供快速失败机制。具体在像add,remove方法中,增加modCount的值,每次调用加1。然后利用它,决定是否抛出ConcurrentModificationExceptions
*/
protected transient int modCount = 0;
接着看ArrayList类方法
/**
* Returns an iterator over the elements in this list in proper sequence.
* 这个方法,返回一个本身list的一个iterator
* <p>The returned iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
*
* @return an iterator over the elements in this list in proper sequence
*/
public Iterator<E> iterator() {
return new Itr();//关键这个类
}
再看 Itr类
/**
* An optimized version of AbstractList.Itr
*/
private class Itr implements Iterator<E> {
int cursor; // index of next element to return //有个潜台词,默认值是0,list当前的下标
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;//初始化时候,会把list原来的修改次数,赋给expectedModCount
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();//会抛出java.util.ConcurrentModificationException异常
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;//每次,移动下标加1,下次的游标位置
return (E) elementData[lastRet = i];//lastRet 赋值本次的坐标。
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();//会抛出java.util.ConcurrentModificationException异常
try {
ArrayList.this.remove(lastRet);//根据下标删除元素,ArrayList.this.remove()方法,会modCount++;
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;//让后又把最新的modCount 赋给expectedModCount,这样保证,通过Itr remove方法删除元素,不会抛ConcurrentModificationException异常,因为expectedModCount == modCount
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
final void checkForComodification() {//抛出java.util.ConcurrentModificationException异常的方法
if (modCount != expectedModCount)//如果modCount 不等于expectedModCount 就抛出这个异常
throw new ConcurrentModificationException();
}
}
最后,再回来说ConcurrentModificationException异常,直接一点,它的作用是,一个集合(list 实现,比如ArrayList,LinkedList,Vertor 等AbstractList子类), 在用它自己的Iterator对象 在玩转它本身时(next,remove,add,previous 调用)时,如果发现有其他方式(非这个Iterator 对象), 修改这个list对象,就会(通过比较modCount, expectedModCount值)抛出ConcurrentModificationException异常。由于 Iterator 对象不是线程安全的,在多线程中用it.remove()删除元素,同样可以抛出 ConcurrentModificationException异常 !