2013-03-06 60 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>()实例即可。

请注意,我建议的修复旨在修复异常,同时保持代码流和逻辑不变,因为我只对解决方案有限制。