Javaコレクションでよく見られるcheckForComodification()メソッドの役割?modCountとexpectedModCountの役割は?

6648 ワード

主にfail-fastメカニズムを実現するために使用されます
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();
}