Java 集合中常见 checkForComodification()方法的作用? modCount和expectedModCount作用?

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_40254498/article/details/81386920

主要是用来实现fail-fast机制

有两个线程(线程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 <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.
 *
 * <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.
 *
 * <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.
 */
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()接口,其中也定义了一个int型的属性:expectedModCount,这个属性在Itr类初始化时被赋予ArrayList对象的modCount属性的值。

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();
}
上一篇:Linux Shell 字符串操作(长度/查找/替换)详解


下一篇:linux tr命令详解 在处理字符串大写 转小写时候找到的 特此记录