迭代时出现奇怪的 ConcurrentModificationException
A strange ConcurrentModificationException on iteration
this
可能是最接近我的情况,但这也没有帮助。
我在这里收到 ConcurrentModificationException:
for (Iterator<ProjectileBase> iterator = projectiles.iterator(); iterator.hasNext();) {
ProjectileBase proj = iterator.next(); < here
if (proj == null || !proj.isValid()) {
iterator.remove();
continue;
}
if (((!proj.ignoreRange()) ? proj.lived <= proj.data.getRange() : true)){
proj.lived++;
proj.onTick();
} else {
MissileHitEvent event = new MissileHitEvent(proj.shooter, proj.wand, proj, false, null);
Bukkit.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
iterator.remove();
continue;
} else {
proj.lived = 0;
}
}
}
尽管我按照建议做了here
?
列表是这样指定的:
private List<ProjectileBase> projectiles = new ArrayList<ProjectileBase>();
在 class 构造中初始化。有什么问题吗?
编辑: 控制台日志:
[10:01:58] [Craft Scheduler Thread - 3754/WARN]: Exception in thread "Craft Scheduler Thread - 3754"
[10:01:58] [Craft Scheduler Thread - 3754/WARN]: org.apache.commons.lang.UnhandledException: Plugin MagicWands v1.0 generated an exception while executing task 247
at org.bukkit.craftbukkit.v1_9_R2.scheduler.CraftAsyncTask.run(CraftAsyncTask.java:57)
at com.destroystokyo.paper.ServerSchedulerReportingWrapper.run(ServerSchedulerReportingWrapper.java:22)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at io.jettymc.DataHolders.ProjectileManager.iterate(ProjectileManager.java:117)
at io.jettymc.DataHolders.ProjectileManager.run(ProjectileManager.java:232)
at org.bukkit.craftbukkit.v1_9_R2.scheduler.CraftTask.run(CraftTask.java:58)
at org.bukkit.craftbukkit.v1_9_R2.scheduler.CraftAsyncTask.run(CraftAsyncTask.java:53)
... 4 more
编辑 2: 好吧,我想值得一提的是,我正在 Bukkit/Spigot(Minecraft 服务器和 API)上构建这个项目。但我怀疑这是这个错误的原因?
查看 ConcurrentModificationException 和 ArrayList 的文档
https://docs.oracle.com/javase/7/docs/api/java/util/ConcurrentModificationException.html
https://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html
要解决您的问题,请检查以下代码。
例如,
import java.util.*;
public class HelloWorld{
public static void main(String []args){
List<String> animals = new ArrayList<>();
animals.add("Cat1");
animals.add("Cat2");
animals.add("Cat3");
animals.add("Cat4");
animals.add("Cat5");
for(ListIterator<String> iterator = animals.listIterator(); iterator.hasNext();) {
String name = iterator.next();
if (name.equals("Cat2")) {
iterator.remove();
continue;
}
System.out.println(name);
}
}
}
干杯!!!
为了帮助缩小问题范围,有一个技巧可能会有所帮助。
假设 projectiles
是对 ArrayList
的唯一引用,您可以在迭代时临时用不可变列表替换它,因此只有 Iterator
可以修改列表。如果其他一些代码试图修改列表,则会发生异常,假设您的错误处理没有搞砸,这应该让您知道它发生在哪里。
示例:
List<ProjectileBase> projectilesHold = projectiles;
projectiles = Collections.unmodifiableList(projectiles);
try {
for (Iterator<ProjectileBase> iterator = projectilesHold.iterator(); iterator.hasNext();) {
// other code here is unchanged
}
} finally {
projectiles = projectilesHold;
}
代码将可修改列表保存在"hold"变量中,然后将列表包装起来使其不可修改。 finally
块将确保恢复可修改列表,无论如何。
for
循环迭代器随后被修改为使用 "hold" 中的可修改列表,因此其 remove()
方法有效,但 projectiles
字段现在在其他任何地方在迭代期间不可修改。
这仅用于调试。确定问题并改正后,再次删除逻辑。
this 可能是最接近我的情况,但这也没有帮助。
我在这里收到 ConcurrentModificationException:
for (Iterator<ProjectileBase> iterator = projectiles.iterator(); iterator.hasNext();) {
ProjectileBase proj = iterator.next(); < here
if (proj == null || !proj.isValid()) {
iterator.remove();
continue;
}
if (((!proj.ignoreRange()) ? proj.lived <= proj.data.getRange() : true)){
proj.lived++;
proj.onTick();
} else {
MissileHitEvent event = new MissileHitEvent(proj.shooter, proj.wand, proj, false, null);
Bukkit.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
iterator.remove();
continue;
} else {
proj.lived = 0;
}
}
}
尽管我按照建议做了here ?
列表是这样指定的:
private List<ProjectileBase> projectiles = new ArrayList<ProjectileBase>();
在 class 构造中初始化。有什么问题吗?
编辑: 控制台日志:
[10:01:58] [Craft Scheduler Thread - 3754/WARN]: Exception in thread "Craft Scheduler Thread - 3754"
[10:01:58] [Craft Scheduler Thread - 3754/WARN]: org.apache.commons.lang.UnhandledException: Plugin MagicWands v1.0 generated an exception while executing task 247
at org.bukkit.craftbukkit.v1_9_R2.scheduler.CraftAsyncTask.run(CraftAsyncTask.java:57)
at com.destroystokyo.paper.ServerSchedulerReportingWrapper.run(ServerSchedulerReportingWrapper.java:22)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at io.jettymc.DataHolders.ProjectileManager.iterate(ProjectileManager.java:117)
at io.jettymc.DataHolders.ProjectileManager.run(ProjectileManager.java:232)
at org.bukkit.craftbukkit.v1_9_R2.scheduler.CraftTask.run(CraftTask.java:58)
at org.bukkit.craftbukkit.v1_9_R2.scheduler.CraftAsyncTask.run(CraftAsyncTask.java:53)
... 4 more
编辑 2: 好吧,我想值得一提的是,我正在 Bukkit/Spigot(Minecraft 服务器和 API)上构建这个项目。但我怀疑这是这个错误的原因?
查看 ConcurrentModificationException 和 ArrayList 的文档
https://docs.oracle.com/javase/7/docs/api/java/util/ConcurrentModificationException.html
https://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html
要解决您的问题,请检查以下代码。
例如,
import java.util.*;
public class HelloWorld{
public static void main(String []args){
List<String> animals = new ArrayList<>();
animals.add("Cat1");
animals.add("Cat2");
animals.add("Cat3");
animals.add("Cat4");
animals.add("Cat5");
for(ListIterator<String> iterator = animals.listIterator(); iterator.hasNext();) {
String name = iterator.next();
if (name.equals("Cat2")) {
iterator.remove();
continue;
}
System.out.println(name);
}
}
}
干杯!!!
为了帮助缩小问题范围,有一个技巧可能会有所帮助。
假设 projectiles
是对 ArrayList
的唯一引用,您可以在迭代时临时用不可变列表替换它,因此只有 Iterator
可以修改列表。如果其他一些代码试图修改列表,则会发生异常,假设您的错误处理没有搞砸,这应该让您知道它发生在哪里。
示例:
List<ProjectileBase> projectilesHold = projectiles;
projectiles = Collections.unmodifiableList(projectiles);
try {
for (Iterator<ProjectileBase> iterator = projectilesHold.iterator(); iterator.hasNext();) {
// other code here is unchanged
}
} finally {
projectiles = projectilesHold;
}
代码将可修改列表保存在"hold"变量中,然后将列表包装起来使其不可修改。 finally
块将确保恢复可修改列表,无论如何。
for
循环迭代器随后被修改为使用 "hold" 中的可修改列表,因此其 remove()
方法有效,但 projectiles
字段现在在其他任何地方在迭代期间不可修改。
这仅用于调试。确定问题并改正后,再次删除逻辑。