Java ArrayList.addAll()ConcurrentModificationException

Java ArrayList.addAll()ConcurrentModificationException,java,Java,在Java8(OpenJDK)中实现一种Kademlia bucket时,我遇到了一些非常奇怪的问题 我需要从所谓的桶中获取至少特定数量的物品。 但这不是问题所在 不知何故,我在ArrayList上执行closest.addAll()时有时会遇到ConcurrentModificationException,尽管它仅用于单个线程,我没有迭代或做类似的事情 你知道怎么帮我吗? 这是我的代码(我知道它很乱!) List getClosest(节点n,int num){ ArrayList最近=新的A

在Java8(OpenJDK)中实现一种Kademlia bucket时,我遇到了一些非常奇怪的问题

我需要从所谓的桶中获取至少特定数量的物品。 但这不是问题所在

不知何故,我在ArrayList上执行closest.addAll()时有时会遇到ConcurrentModificationException,尽管它仅用于单个线程,我没有迭代或做类似的事情

你知道怎么帮我吗? 这是我的代码(我知道它很乱!)

List getClosest(节点n,int num){
ArrayList最近=新的ArrayList();
int缺失;
int walkDown=n.getBucket(me);
int walkUp=walkDown+1;
布尔值pleaseBreak=true;
while(true){
missing=num-最近的.size();
如果(缺失=0&&walkUp<160){
列表l=存储桶[walkUp].getClosest(缺少);
最近的。addAll(l);
如果(最接近的.size()>=缺失){
返回最近的位置;
}
walkUp++;
pleaseBreak=假;
}
如果(巡检>=0&&walkDown<160){
列表l=存储桶[walkDown].getClosest(缺少);
最近的。addAll(l);
如果(最接近的.size()>=缺失){
返回最近的位置;
}
徒步旅行--;
pleaseBreak=假;
}
如果(请用break){
返回最近的位置;
}
请说实话;
}
}
实际上意味着您在迭代列表时以某种方式修改列表,从而打破了迭代规则

请注意,此异常并不总是表示对象已被其他线程并发修改。如果单个线程发出一系列违反对象约定的方法调用,该对象可能会引发此异常例如,如果线程在使用fail fast迭代器迭代集合时直接修改集合,迭代器将引发此异常

也就是说,造成这一问题的原因相当清楚。由于
最近的
是一个新的
列表
,由正在修改的方法填充,因此它必须是
l

有两种选择:

  • 另一个线程正在这样做
  • 您已经在列表中打开了一个迭代器
    l
  • 假设不是1(或者你可能会提到),我会选择:

    您的
    getClosest
    方法返回正在迭代和/或修改的列表的子列表,
    addAll
    也在尝试迭代该列表


    要修复此问题,请使
    getClosest
    返回子列表的副本。

    什么类型的
    bucket[walkDown]
    ?你能显示
    getClosest(missing)
    的代码吗?这看起来不错,请提供一个请发布堆栈跟踪。可能是重复的谢谢,我真是个白痴。现在,它工作得很好,我只是使用了一个复制构造函数。@Marcel-这是一个常见的错误。复制构造函数是一个很好的解决方案。
    List<Neighbour> getClosest(Node n, int num) {
        ArrayList<Neighbour> closest = new ArrayList<>();
        int missing;
        int walkDown = n.getBucket(me);
        int walkUp = walkDown + 1;
        boolean pleaseBreak = true;
        while (true) {
            missing = num - closest.size();
            if (missing <= 0) {
                return closest;
            }
    
            if (walkUp >= 0 && walkUp < 160) {
                List<Neighbour> l = buckets[walkUp].getClosest(missing);
                closest.addAll(l);
                if (closest.size() >= missing) {
                    return closest;
                }
                walkUp++;
                pleaseBreak = false;
            }
    
            if (walkDown >= 0 && walkDown < 160) {
                List<Neighbour> l = buckets[walkDown].getClosest(missing);
                closest.addAll(l);
                if (closest.size() >= missing) {
                    return closest;
                }
                walkDown--;
                pleaseBreak = false;
            }
    
            if (pleaseBreak) {
                return closest;
            }
            pleaseBreak = true;
        }
    }