Javaコレクションでよく見られるcheckForComodification()メソッドの役割?modCountとexpectedModCountの役割は?
2つのスレッド(スレッドA、スレッドB)があり、スレッドAはlist、スレッドBを巡回してlistを変更します.-スレッドAは、listプロシージャを巡回している間(expectedModCount=modCount=N)、スレッドが起動し、スレッドBに要素が追加されます.これは、modCountの値が変更されます(modCount+1=N+1).スレッドAがnextメソッドの実行を続行すると、checkForComodificationメソッドにexpectedModCount=Nが見つかり、modCount=N+1が等しくないことが通知されます.この場合、ConcurrentModificationException異常が投げ出され、fail-fastメカニズムが生成されます.
/**
* JDK1.8 ArrayList
*/
/**
* The number of times this list has been structurally modified.
* 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.
*
* 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
* fail-fast behavior, rather than non-deterministic behavior in
* the face of concurrent modification during iteration.
*
*
Use of this field by subclasses is optional. 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.
*/
protected transient int modCount = 0;
親AbstractListでint型の属性を定義しました:modCount
protected transient int modCount = 0;
ArrayListの構造変化に関連するすべての方法においてmodCountの値を増加させ、add()、remove()、addAll()、removeRange()、clear()の方法を含む.これらのメソッドは呼び出されるたびにmodCountの値に1を加算します.
:add() addAll() modCount ensureCapacity() 。
AbstractListのiterator()メソッド(ArrayListはこのメソッドを直接継承)プライベート内部メンバークラスItrを使用して、Itrオブジェクト(Iteratorインタフェース)の戻り値を生成します.public Iterator iterator() { return new Itr(); }
Itrは、Iterator()インタフェースを実装し、Itrクラスの初期化時にArrayListオブジェクトのmodCount属性の値が付与されるint型の属性:expectedModCountも定義する.
int expectedModCount = modCount;
: Itr ArrayList , AbstractList 。 ,Itr 。
Itr.hasNext()メソッドでは、次のようになります.
public boolean hasNext() { return cursor != size; }
AbstractListのsizeを呼び出し、現在のカーソル位置が境界を越えているかどうかを比較します.
public Object next()
{
try
{
Object next = get(cursor);
checkForComodification();
lastRet = cursor++;
return next;
}
catch(IndexOutOfBoundsException e)
{
checkForComodification();
throw new NoSuchElementException();
}
}
/**
* ,
* add() remove() 。
* AbstractList , 。
* modCount expectedModCount
*/
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}