ArrayList.addAll()ConcurrentModificationException

时间:2015-01-22 11:49:34

标签: java

在Java 8(OpenJDK)中实现一种Kademlia存储桶时,我遇到了一些非常奇怪的问题。

我需要从所谓的Buckets中获得至少一定数量的物品。 但那不是问题。

不知何故,我在ArrayList上执行nearest.addAll()时有时会遇到ConcurrentModificationException,虽然它只是在单个线程中使用而我没有迭代或做类似的事情。

你知道如何帮助我吗? 这是我的代码(我知道这是一团糟!):

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

1 个答案:

答案 0 :(得分:3)

ConcurrentModificationException实际上意味着你在迭代时通过某种方式修改列表来破坏迭代规则。

  

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

那说很明显可能导致这个问题。由于closest是由方法填充的新List,因此必须l进行修改。

有两种选择:

  1. 另一个主题是这样做。
  2. 您已经在列表l中打开了一个迭代器。
  3. 假设它不是 1 (或者您可能已经提到过),我会选择:

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

    要解决此问题,请getClosest返回子列表的副本