java.util.ConcurrentModificationException但我没有删除

时间:2014-11-20 21:04:56

标签: java recursion concurrentmodification continue

我的下面的递归函数在'continue'语句中抛出ConcurrentModificationException。我查看了一些有关ConcurrentModificationException的帖子,所有问题似乎都是从元素中删除元素,但我没有删除函数中的任何元素。

我的功能如下:

    public static void getRootedTreeHelper(Node n, boolean[] marked, String spacing){ 

        System.out.println(spacing + "in helper with " + n.getId());
        marked[n.getId()] = true;
        if(n.children.isEmpty())
            return;
        else{
            for(Node child : n.children){
                if(marked[child.getId()])
                    continue; // ConcurrentModificationException is thrown here. 
                else{
                    n.addChild(child);
                    spacing = spacing + "\t";
                    getRootedTreeHelper(child, marked, spacing);
                }
            }
        }
    }

根据要求:Node Class的相关部分如下所示

public class Node {

    private int id;
    ArrayList<Node> children;

    public Node(int id) {
        this.id = id;
        children = new ArrayList<Node>();
    }

    /**
     * add node n to this node's children
     * @param n
     */
    public void addChild(Node n) {
        children.add(n);
    }

    // getters and setters()
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
}

有没有人有任何想法?

编辑已解决: 我使用for循环,而不是使用for循环遍历所有子循环。

2 个答案:

答案 0 :(得分:4)

如果您查看Iterator的ArrayList实现,它会显示在Iterator.next()期间它会检查集合的大小是否已更改。

if (i >= elementData.length)
  throw new ConcurrentModificationException();

即使使用Collections.synchronizedList(n.children)的同步版本也不会有帮助,因为它仍然使用相同的迭代器。

因此,如果您需要具有修改集合的并发访问权限,您可以选择:

  • 使用Iterator.remove()删除当前元素
  • 使用允许同时修改的版本,例如ConcurrentLinkedQueueConcurrentLinkedDeque
  • 使用另一个List来编写更改而不是迭代。

你可以尝试一下LinkedList - 我还没有完全阅读这个来源,但是快速浏览一下它的Iterator似乎在迭代时不会对添加内容产生影响。

答案 1 :(得分:2)

来自ConcurrentModificationException Javadoc:

  

请注意,此异常并不总是表示对象具有   由不同的线程同时修改。 (...)对于
  例如,如果一个线程在它是
时直接修改了一个集合   使用失败快速迭代器迭代器迭代集合   将抛出此异常。

该错误是将一个孩子添加到集合中,同时也迭代它。

当迭代器在for循环中递增时,迭代器仅检测到