2016-08-24 142 views
1

這個問題是關於JDK 1.8.0_74的。班級是java.util.ArrayList$Itr。當調用ArrayList#iterator()方法時,會返回此(內部)類的實例。具體地講,我的問題是關於next()方法上Itr什麼時候ArrayList.Itr#next()在這一行上拋出ConcurrentModificationException?

850  public E next() { 
851   checkForComodification(); 
852   int i = cursor; 
853   if (i >= size) 
854    throw new NoSuchElementException(); 
855   Object[] elementData = ArrayList.this.elementData; 
856   if (i >= elementData.length) 
857    throw new ConcurrentModificationException(); 
858   cursor = i + 1; 
859   return (E) elementData[lastRet = i]; 
860  } 

我明白的理由[1]對於checkForComodification呼叫在線路#851我也明白(i >= size)檢查[2]線#853

但是,在#856線上檢查if (i >= elementData.length)是在防範什麼情況?

在單線程代碼,我不能對代碼做一些失敗,ConcurrentModificationException上線#857

[1]:迭代器創建後結構修改失敗:

static void coMod() { 
     ArrayList<Integer> list = new ArrayList<>(4); 
     list.add(1); 
     list.add(2); 
     Iterator<Integer> itr = list.iterator(); 
     list.remove(0); //structural modification after iterator creation 
     if (itr.hasNext()) { 
      System.out.println("wait, there's more!"); 
      itr.next(); // modification while iterating -- 
         // fails at java.util.ArrayList$Itr.next(ArrayList.java:851) 
     } 
    } 

[2]:失敗迭代器已到達結尾之後

static void noHasNext() { 
    ArrayList<Integer> list = new ArrayList<>(4); 
    Iterator<Integer> itr = list.iterator(); 
    itr.next(); // unguarded next call -- 
       // fails at java.util.ArrayList$Itr.next(ArrayList.java:854) 
} 
+1

「在一個單一的線程代碼」 - 這可能是這裏的重要因素... –

+0

我明白了,但'ArrayList'不是線程安全的;那麼它需要檢查嗎? –

+0

這只是一個調試工具 - 事實上它甚至提到在Javadoc的介紹中:https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html –

回答

0

這是有可能只發生在多螺紋狀況。

我相信線程1將不得不立即停止執行855行之前。線程2會來,並將ArrayList.this.elementData設置爲一個新的(小)數組。

這是一個便宜的檢查,以提供比拋出的ArrayIndexOutOfBoundsException異常更好的異常。從理論上講,優化器甚至可能會檢測到顯式檢查數組邊界並忽略對ArrayIndexOutOfBoundsException的檢查。

+0

這是不正確的,「這是隻能發生在多線程情況下」。 –

+0

@LewBloch解釋如何在單線程情況下發生。問題是具體詢問何時在857行發生異常,而不是一般情況。 checkForComodification()是修改的普通(單線程)檢查。 – Matt

+0

我誤解了這個問題。我立場糾正。 –

相關問題