在很多的结构中(ArrayList、LinkedList、PriorityQueue等),这些结构的特点就是:线程不安全,它们都有modCount字段,从字面上看该modCount保持了结构被修改的次数,这个次数有什么用呢?
下面以JDK ArrayList为例,看看modCount有什么作用
/**
* An optimized version of AbstractList.Itr
*/
/**
* ArrayList内部类
**/
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; /* expectedModCount 初始化为modCount */
Itr() {}
public boolean hasNext() {
return cursor != size;
}
final void checkForComodification() {
/**
* 如果modCount != expectedModCount 抛出异常。
**/
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
@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();
}
}
@Override
@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> consumer) {
Objects.requireNonNull(consumer);
final int size = ArrayList.this.size;
int i = cursor;
if (i >= size) {
return;
}
final Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length) {
throw new ConcurrentModificationException();
}
while (i != size && modCount == expectedModCount) {
consumer.accept((E) elementData[i++]);
}
// update once at end of iteration to reduce heap write traffic
cursor = i;
lastRet = i - 1;
checkForComodification();
}
}
总结:由于线程不安全,在操作迭代器Iterator过程中,如果ArrayList元素改变了,比如增加了新元素或减少新元素,那么Iterator就应该停止,因为此时ArrayList改变了,继续迭代有可能出现不可预知的情况,JDK对于这种情况,直接会抛出异常ConcurrentModificationException。