1. 程式人生 > >JDK1.8 java.util.ConcurrentModificationException錯誤

JDK1.8 java.util.ConcurrentModificationException錯誤

一,示例程式碼:

List list = new ArrayList();

list.add(1);  
list.add(2);
list.add(3);
Iterator it = list.iterate(); 
while(it.hasNext()) {
    Object obj = it.next();
    list.remove(1);
}

此時絕逼會拋java.util.ConcurrentModificationException錯誤,怎麼會呢,仔細檢視JDK,原來如此

注意,此實現不是同步的。如果多個執行緒同時訪問一個 ArrayList 例項,而其中至少一個執行緒從結構上修改了列表,那麼它必須 保持外部同步。(結構上的修改是指任何新增或刪除一個或多個元素的操作,或者顯式調整底層陣列的大小;僅僅設定元素的值不是結構上的修改。)這一般通過對自然封裝該列表的物件進行同步操作來完成。如果不存在這樣的物件,則應該使用 Collections.synchronizedList 方法將該列表“包裝”起來。這最好在建立時完成,以防止意外對列表進行不同步的訪問:
List list = Collections.synchronizedList(new ArrayList(...));
此類的 iterator 和 listIterator 方法返回的迭代器是快速失敗的:在建立迭代器之後,除非通過迭代器自身的 remove 或 add 方法從結構上對列表進行修改,否則在任何時間以任何方式對列表進行修改,迭代器都會丟擲 ConcurrentModificationException。因此,面對併發的修改,迭代器很快就會完全失敗,而不是冒著在將來某個不確定時間發生任意不確定行為的風險。

二,解決辦法:

  1.  // 1 使用Iterator提供的remove方法,用於刪除當前元素  
  2.  for (Iterator<String> it = myList.iterator(); it.hasNext();) {  
  3.      String value = it.next();  
  4.       if
     (value.equals( "3")) {  
  5.           it.remove();  // ok  
  6.      }  
  7. }  
  8. System. out.println( "List Value:" + myList.toString());  
  9.   
  10.  // 2 建一個集合,記錄需要刪除的元素,之後統一刪除               
  11. List<String> templist = new ArrayList<String>();  
  12.  for (String value : myList) {  
  13.       if (value.equals( "3")) {  
  14.           templist.remove(value);  
  15.      }  
  16. }  
  17.  // 可以檢視removeAll原始碼,其中使用Iterator進行遍歷  
  18. myList.removeAll(templist);  
  19. System. out.println( "List Value:" + myList.toString());          
  20.   
  21.   // 3. 使用執行緒安全CopyOnWriteArrayList進行刪除操作  
  22. List<String> myList = new CopyOnWriteArrayList<String>();  
  23. myList.add( "1");  
  24. myList.add( "2");  
  25. myList.add( "3");  
  26. myList.add( "4");  
  27. myList.add( "5");  
  28.   
  29. Iterator<String> it = myList.iterator();  
  30.   
  31.  while (it.hasNext()) {  
  32.      String value = it.next();  
  33.       if (value.equals( "3")) {  
  34.           myList.remove( "4");  
  35.           myList.add( "6");  
  36.           myList.add( "7");  
  37.      }  
  38. }  
  39. System. out.println( "List Value:" + myList.toString());  
  40.   
  41.  // 4. 不使用Iterator進行遍歷,需要注意的是自己保證索引正常  
  42.  for ( int i = 0; i < myList.size(); i++) {  
  43.      String value = myList.get(i);  
  44.      System. out.println( "List Value:" + value);  
  45.       if (value.equals( "3")) {  
  46.           myList.remove(value);  // ok  
  47.           i--; // 因為位置發生改變,所以必須修改i的位置  
  48.      }  
  49. }  
  50. System. out.println( "List Value:" + myList.toString()); 


這裡有很棒得一個總結