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