有时接收java.util.ConcurrentModificationException,有时不接收。无法弄清楚为什么

时间:2014-03-04 17:11:23

标签: java crash render

首先,这里是错误消息:

线程“Thread-2”中的异常
  java.util.ConcurrentModificationException
  at java.util.ArrayList $ Itr.checkForComodification(Unknown Source)
  at java.util.ArrayList $ Itr.next(Unknown Source)
  在zom.mainpac.Game.render(Game.java:218)
  在zom.mainpac.Game.run(Game.java:154)
  在java.lang.Thread.run(未知来源)

在第218行渲染对象的ArrayList:

    for(Objects e : list){
    e.render(g);
    }

然后我在第154行的渲染功能:

    render();

...

private void render() {

    BufferStrategy bufferStrategy = this.getBufferStrategy();

    if (bufferStrategy == null) {

        this.createBufferStrategy(2);
        return;

    }

问题可能是因为我的笔记本电脑无法呈现所有对象 SOMETIMES ,所以它放弃了。所以我只是想知道是否有更好的方法可以做到这一点,而不会一直崩溃。

3 个答案:

答案 0 :(得分:2)

您遇到线程安全问题和/或列表访问问题。您可能希望将列表/数组项复制到局部变量中,以便在遍历和/或考虑同步块时无法修改列表。

您的实例列表变量正由一个线程访问(执行for循环),然后另一个线程出现,可能它想要访问它。要解决而不是使用实例变量执行for循环,请创建一个局部变量并从.list中复制项目。现在你有一个其他线程无法访问的私人列表

答案 1 :(得分:1)

问题发生的原因是您的代码在迭代时修改了列表。

  • 如果您只有一个线程可以从/向列表读/写,那么最有可能是调用

    this.createBufferStrategy(2);

有时会将一些元素添加到同一个数组列表中。如果要使用列表副本进行迭代,则可以修复异常:

for (Objects e : new ArrayList(list)) {
   e.render(g);
}
  • 如果您有多个线程来读取/写入列表,请使用java.util.concurrent.CopyOnWriteArrayList代替

答案 2 :(得分:0)

For Each使用迭代器来进行循环,因此如果您碰巧从该列表中删除了某些内容,则在迭代期间您很容易受到此类异常的影响。例如,如果您在渲染时从游戏列表中删除图块或精灵,就会发生这种情况。如果您不修改List,那么通常可以使用CopyOnWriteArrayList,如果您希望在迭代时修改List(让您不必创建列表的副本),但重要的是要注意您应该首先了解导致的行为这个而不是盲目修复。