2013-03-06 99 views
0

我在for(Entry ...)循環中得到一個錯誤,在調用dfs()之後,它會說concurrentmodificationexception。即使visitedOrder與foreach循環無關,我也不知道它爲什麼會發生。這怎麼解決?Java:併發修改異常

public TreeMap<Integer, Integer> DFS() 
{ 
    TreeMap<Integer, Integer> stack = new TreeMap<Integer, Integer>(); 
    TreeMap<Integer, Integer> visitedOrder = stack; 
    for(int i = 1; i < graph[0].length-1; i++) 
    { 
     stack.put(i, 0); 
    } 
    for(Entry<Integer, Integer> vertex : stack.entrySet()) 
    { 
     if(vertex.getValue() == 0) 
      dfs(vertex.getKey(), visitedOrder); 
    } 
    System.out.println(visitedOrder.values()); 
    return visitedOrder; 
} 

public void dfs(int vertex, TreeMap<Integer, Integer> visited) 
{ 
    visited.put(vertex, order++); 
    int currVertex = vertex; 
    for(int i = vertex; i < graph[0].length-1;i++) 
    { 
     if(graph[vertex][i+1] == 1) 
     { 
      dfs(++currVertex, visited); 
      break; 
     } 
     currVertex++; 
    } 
} 
+0

您的地圖被多個線程訪問,其中一個線程修改地圖內容(使用'dfs'方法),而其他線程瀏覽地圖內容。爲了解決這個問題,你可以使用一個鎖對象來同步代碼塊。 – 2013-03-06 04:15:20

+0

雖然我有2個樹形圖。我認爲這會解決它? – user1375155 2013-03-06 04:17:40

+1

如果兩個圖都指向相同的地圖對象參考,則不適用。 – 2013-03-06 04:18:50

回答

2

這裏是 「類ConcurrentModificationException的」 的Javadoc:

此異常可通過方法拋出已檢測到的併發 修改一個對象的當這種修改是不允許的。

例如,一個線程在另一個線程遍歷它時通常不允許修改Collection。一般而言,在這些情況下迭代的結果是不確定的。 某些迭代器實現(包括由JRE提供的所有通用 目的集合實現的實現)可能選擇 如果檢測到此行爲則拋出此異常。迭代器做 這就是所謂的快速迭代器,因爲它們很快就會失敗,並且會在未來的未定時間冒着任意的非確定性行爲冒險。

請注意,此例外情況並不總是表明某個對象已由另一個線程同時修改了 。如果單個線程 發出一系列方法調用違反對象的合約 ,該對象可能會拋出此異常。例如,如果 線程正在使用故障快速迭代器迭代 集合時直接修改集合,則迭代器將拋出此異常。

碰巧,那正是你在做的:修改你在「foreach」循環中使用的結構。

解決方法:

如果你認爲你的設計是正確的,則替換一個簡單的for循環:for (int i=0; i < myContainer.size(); i++) ...

+3

值得澄清的是,您的解決方法不是「修復」 - ConcurrentModificationException是一個合法的指示符,表示編寫的代碼存在潛在的問題。有時可以使用此解決方法並取消此異常。然而,如果不理解爲什麼會發生這種情況,那麼這種情況將成爲麻煩事的一個方法。 – dimo414 2013-03-06 04:24:15

1

我不知道爲什麼它即使visitedOrder不 與foreach循環有關的發生。

您正在閱讀時試圖修改TreeMap。 你只是在這一行中指出參考。所以它只是具有不同引用名稱的同一個TreeMap。

TreeMap<Integer, Integer> stack = new TreeMap<Integer, Integer>(); 
    TreeMap<Integer, Integer> visitedOrder = stack; 
0

還有當你做一個new TreeMap<Integer, Integer>()所創建只是一個TreeMap實例。 stack變量指的是這個實例;變量visitedOrder也指同一個實例。當您撥打dfs(int vertex, TreeMap<Integer, Integer> visited)時,visited參數也指示相同的TreeMap實例。

現在您正在遍歷for(Entry<Integer,...循環中此TreeMap實例的條目集。迭代時,您調用dfs(int, TreeMap<Interge, Integer>)方法,並在此方法中調用TreeMap實例上的put並修改該實例;因此ConcurrentModificationException

從您提供的代碼中,我的理解是您正試圖通過執行DFS將數組轉換爲TreeMap。您正在遍歷由stack引用的TreeMap並嘗試填充visitedOrder。要解決您遇到的異常,只需將visitedorder變量指向new TreeMap<Integer, Integer>()實例即可。

請注意,我建議的修復旨在修復異常,同時保持代碼流和邏輯不變,因爲我只對解決方案有限制。