我的下面的递归函数在'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循环遍历所有子循环。
答案 0 :(得分:4)
如果您查看Iterator的ArrayList
实现,它会显示在Iterator.next()
期间它会检查集合的大小是否已更改。
if (i >= elementData.length)
throw new ConcurrentModificationException();
即使使用Collections.synchronizedList(n.children)
的同步版本也不会有帮助,因为它仍然使用相同的迭代器。
因此,如果您需要具有修改集合的并发访问权限,您可以选择:
Iterator.remove()
删除当前元素ConcurrentLinkedQueue
或ConcurrentLinkedDeque
或List
来编写更改而不是迭代。你可以尝试一下LinkedList
- 我还没有完全阅读这个来源,但是快速浏览一下它的Iterator
似乎在迭代时不会对添加内容产生影响。
答案 1 :(得分:2)
来自ConcurrentModificationException
Javadoc:
请注意,此异常并不总是表示对象具有 由不同的线程同时修改。 (...)对于
例如,如果一个线程在它是
时直接修改了一个集合 使用失败快速迭代器迭代器迭代集合 将抛出此异常。
该错误是将一个孩子添加到集合中,同时也迭代它。
当迭代器在for
循环中递增时,迭代器仅检测到 。