天天看點

主題:為什麼會出現 java.util.ConcurrentModificationException 異常?

在Map或者Collection的時候,不要用它們的API直接修改集合的内容(否則會出現 java.util.ConcurrentModificationException 異常),如果要修改可以用Iterator的remove()方法,例如:

Java代碼

主題:為什麼會出現 java.util.ConcurrentModificationException 異常?
主題:為什麼會出現 java.util.ConcurrentModificationException 異常?
主題:為什麼會出現 java.util.ConcurrentModificationException 異常?
  1.  public void setReparation( Reparation reparation ) {   
  2.      for (Iterator it = this.reparations.iterator();it.hasNext();){    //reparations為Collection   
  3.          Reparation repa = (Reparation)it.next();   
  4.          if (repa.getId() == reparation.getId()){   
  5.              this.reparations.remove(repa);   
  6.              this.reparations.add(reparation);   
  7.          }   
  8.      }   
  9. }  
public void setReparation( Reparation reparation ) {
        for (Iterator it = this.reparations.iterator();it.hasNext();){    //reparations為Collection
            Reparation repa = (Reparation)it.next();
            if (repa.getId() == reparation.getId()){
                this.reparations.remove(repa);
                this.reparations.add(reparation);
            }
        }
   }
           

如上寫會在運作期報ConcurrentModificationException,可以如下修改:

Java代碼

主題:為什麼會出現 java.util.ConcurrentModificationException 異常?
主題:為什麼會出現 java.util.ConcurrentModificationException 異常?
主題:為什麼會出現 java.util.ConcurrentModificationException 異常?
  1. public void setReparation( Reparation reparation ) {   
  2.     boolean flag = false;   
  3.     for (Iterator it = this.reparations.iterator();it.hasNext();){    //reparations為Collection   
  4.         Reparation repa = (Reparation)it.next();   
  5.         if (repa.getId() == reparation.getId()){   
  6.             it.remove();   
  7.             flag = true;   
  8.             break;   
  9.         }   
  10.     }   
  11.     if(flag){   
  12.       this.reparations.add(reparation);   
  13.     }   
  14. }  
public void setReparation( Reparation reparation ) {
        boolean flag = false;
        for (Iterator it = this.reparations.iterator();it.hasNext();){    //reparations為Collection
            Reparation repa = (Reparation)it.next();
            if (repa.getId() == reparation.getId()){
                it.remove();
                flag = true;
                break;
            }
        }
        if(flag){
          this.reparations.add(reparation);
        }
    }
           

請問, 按照代碼一寫出現異常的原因是什麼啊?

為什麼使用 Iterator來删除集合裡面的資料就沒有異常呢?

轉:ConcurrentModificationException主要原因及處理方法

2007年04月18日 星期三 12:57

當使用 fail-fast iterator 對 Collection 或 Map 進行疊代操作過程中嘗試直接修改 Collection / Map 的内容時,即使是在單線程下運作,   java.util.ConcurrentModificationException 異常也将被抛出。

  Iterator 是工作在一個獨立的線程中,并且擁有一個 mutex 鎖。 Iterator 被建立之後會建立一個指向原來對象的單鍊索引表,當原來的對象數量發生變化時,這個索引表的内容不會同步改變,是以當索引指針往後移動的時候就找不到要疊代的對象,是以按照 fail-fast 原則 Iterator 會馬上抛出 java.util.ConcurrentModificationException 異常。

  是以 Iterator 在工作的時候是不允許被疊代的對象被改變的。但你可以使用 Iterator 本身的方法 remove() 來删除對象, Iterator.remove() 方法會在删除目前疊代對象的同時維護索引的一緻性。

  有意思的是如果你的 Collection / Map 對象實際隻有一個元素的時候, ConcurrentModificationException 異常并不會被抛出。這也就是為什麼在 javadoc 裡面指出: it would be wrong to write a program that depended on this exception for its correctness: ConcurrentModificationException should be used only to detect bugs.

1 import java.util.*; 

2

3 public final class MyTest 

4 { 

5     private static HashMap p_mapList = new HashMap(2); 

6     private MyTest(){} 

7     public static void init(){ 

8         // If only there are more than one element in Map, 

9         // the ConcurrentModificationException will not be

10         // thrown.

11          p_mapList.put(new String("hello"),new String("world")); 

12          p_mapList.put(new String("goto"),new String("hell")); 

13      } 

14     public static void clear() throws Exception{ 

15          Iterator pTmpKeys = null; 

16          Long pTmpKeyLong; 

17          pTmpKeys = p_mapList.keySet().iterator(); 

18          String pCurKey = null; 

19          String pCurObj = null; 

20         while(pTmpKeys.hasNext()){ 

21              pCurKey = (String) pTmpKeys.next(); 

22              pCurObj = (String) p_mapList.get(pCurKey); 

23

24              p_mapList.put(pCurKey,null); 

25             // You can not remove element in Map object directly.

26             //p_mapList.remove(pCurKey);

27             // But you can remove current element by iterator itself.

28              pTmpKeys.remove(); 

29

30              System.out.println(pCurKey + " removed."); 

31          } 

32          System.out.println(p_mapList.size() +  

33                             " entries left after iterator."); 

34          pTmpKeys = null; 

35      } 

36     public static void main(String[] args) 

37                                  throws Exception{ 

38          MyTest.init(); 

39          MyTest.clear(); 

40      } 

41 }