在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;
}
}
答案 0 :(得分:3)
ConcurrentModificationException实际上意味着你在迭代时通过某种方式修改列表来破坏迭代规则。
请注意,此异常并不总是表示某个对象已被另一个线程同时修改。如果单个线程发出违反对象合同的一系列方法调用,则该对象可能会抛出此异常。 例如,如果线程在使用失败快速迭代器迭代集合时直接修改集合,则迭代器将抛出此异常。
那说很明显可能导致这个问题。由于closest
是由方法填充的新List
,因此必须l
进行修改。
有两种选择:
l
中打开了一个迭代器。假设它不是 1 (或者您可能已经提到过),我会选择:
您的getClosest
方法正在返回正在迭代和/或修改的列表的子列表,addAll
也在尝试迭代它。
要解决此问题,请getClosest
返回子列表的副本。