Java:并发修改异常

时间:2013-03-06 04:12:41

标签: java concurrentmodification

我在for(Entry ...)循环中遇到错误,在调用dfs()之后,它会说parallelmodificationexception。即使visitOrder与foreach循环无关,我也不知道它为什么会发生。如何解决这个问题?

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++;
    }
}

3 个答案:

答案 0 :(得分:2)

这是“Class ConcurrentModificationException”的Javadoc:

  

检测到并发的方法可能抛出此异常   在不允许进行此类修改时修改对象。

     

例如,一个线程通常不允许修改   一个集合,而另一个线程正在迭代它。一般来说,   在这些情况下,迭代的结果是不确定的。   一些迭代器实现(包括所有通用的实现)   由JRE提供的目的集合实现可以选择   如果检测到此行为,则抛出此异常。那个迭代器   这被称为故障快速迭代器,因为它们很快就会失败   干净利落,而不是冒着任意的,非确定性的行为冒险   未来不确定的时间。

     

请注意,此异常并不总是表示对象具有   由另一个线程同时修改。如果是单线程   发出一系列违反合同的方法调用   一个对象,该对象可能抛出此异常。例如,如果是   线程在迭代时直接修改集合   使用失败快速迭代器进行集合,迭代器将抛出此异常   异常。

碰巧,这正是你正在做的事情:修改你在“foreach”循环中使用的结构。

替代方法:

如果你认为你的设计是正确的,那么用一个简单的for循环代替:for (int i=0; i < myContainer.size(); i++) ...

答案 1 :(得分:1)

  

即使visitOrder没有,我也不知道为什么会这样   与foreach循环相关。

您正在尝试在阅读时修改TreeMap。 您只是将此处的引用指向此处。所以它只是具有不同引用名称的相同TreeMap。

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

答案 2 :(得分:0)

只有一个 TreeMap实例在您执行new TreeMap<Integer, Integer>()时创建。 stack变量引用此实例; visitedOrder变量也引用相同的实例。当您致电dfs(int vertex, TreeMap<Integer, Integer> visited)时,visited参数也会引用相同的TreeMap个实例。

现在,您正在迭代TreeMap循环中此for(Entry<Integer,...实例的条目集。在迭代时,您调用dfs(int, TreeMap<Interge, Integer>)方法,并在此方法中,在put实例上调用TreeMap并修改实例;因此ConcurrentModificationException

根据您提供的代码,我的理解是您尝试通过执行DFS将graph数组转换为TreeMap。您正在迭代TreeMap引用的stack并尝试填充visitedOrder。要解决您遇到的异常,只需将visitedorder变量指向new TreeMap<Integer, Integer>()实例。

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