2017-12-18 66 views
0

我從一些教程中瞭解了這個概念,並且只要我知道一個線程正在迭代列表時,允許其他線程修改底層列表,並且我們不會得到ConcurrentModificationException(CME),但是在ArrayList的情況下,我們將獲得CME。CopyOnWriteArrayList(cowal)

但在下面的程序中只有一個線程(主線程),但仍然獲得CME ..爲什麼?

是因爲迭代器?

如果我用COWAL取代AL比我沒有得到任何例外,但我沒有元素「D」以及..爲什麼?

AL<String> l=new AL<>(); 
l.add("a"); 
l.add("b"); 
l.add("c"); 
Iterator<String> itr=l.iterator(); 
l.add("d"); 
while(itr.hasNext()) 
{ 
String s=itr.next(); 
Sop(s); 
} 
+0

我已經做了...「併發收集」 –

+0

如果您將鼠標懸停在它上面,則說明這是.Net概念,而不是JVM。你得到這個異常的原因是因爲在你已經獲得一個迭代器之後你正在改變這個集合(AL) - 這裏涉及到多少個線程並不重要。 – StuartLC

+0

我改變了標籤..didnt通知,因爲它顯示.net的概念.. –

回答

1

錯誤是因爲線

l.add("d"); 

要修改表結構(添加或刪除元素)迭代器創建後。

當您呼叫

itr.next(); 

內部,它是檢查在列表中(添加在ArrayList的或去除)的任何結構改變和它創立存在一個元素添加,因此數組列表的大小已經改變..這就是爲什麼你得到這個例外。

如果你創建的Iterator的前或使用後,迭代器你不會得到這個錯誤添加元素..

下面

是的代碼下一個()的ArrayList類;

 @SuppressWarnings("unchecked") 
    public E next() { 
     checkForComodification(); 
     ...... 
     return (E) elementData[lastRet = i]; 
    } 

    final void checkForComodification() { 
     if (modCount != expectedModCount) 
      throw new ConcurrentModificationException(); 
    } 
1

你得到ConcurrentModificationException因爲ArrayList的迭代器是快速失敗的設計。這意味着一旦迭代器被創建,如果ArrayList被修改(添加或刪除元素),它將拋出ConcurrentModificationException

如果檢查異常日誌聲明,它是在線路String s=itr.next();通過itr.next()方法,因爲通過使用modCount變量,它的副本,同時創造從列表迭代器調用的ArrayList大小的checkForComodification()方法迭代器檢查修飾next()方法拋出。

現在讓我們說說CopyOnWriteArrayList,你沒有得到這個例外是因爲CopyOnWriteArrayList線程安全的變體光盤的ArrayList,其中所有可變操作,比如添加,刪除,設置通過內部陣列複製到新的實現一個用新創建的數組替換舊的數組。

所以,當你從列表中獲得迭代器時,它將保存一個數組的引用,並且當你添加一個元素到列表中時,這個列表就會有全新的數組。迭代器仍然指向舊數組。

您可能已經注意到,聲明l.add("d");中新添加的元素未打印在控制檯上。但如果你打印整個清單,它就在那裏。

這裏是您的示例代碼CopyOnWriteArrayList

List<String> l = new CopyOnWriteArrayList<>(); 
    l.add("a"); 
    l.add("b"); 
    l.add("c"); 
    Iterator<String> itr = l.iterator(); 
    l.add("d"); 
    while (itr.hasNext()) { 
     String s = itr.next(); 
     System.out.println(s); 
    } 
    System.out.println(l); 

輸出是農產品是:

a 
b 
c 
[a, b, c, d] 

希望這有助於。 享受:)

相關問題