ConcurrentModificationException但不从ArrayList中删除任何内容

时间:2016-01-28 19:38:20

标签: java arrays arraylist exception-handling

所以我制作一个游戏并且每5秒就必须产生一个敌人,知道当我运行我的应用程序时它会抛出异常' ConcurrentModificationException'。 这是我的代码的一部分:

private void tick() {

    exec.scheduleAtFixedRate(new Runnable() {
          @Override
          public void run() {
              enemyY = enemyYRand.nextInt(6);
              enemy.add(new Enemy(enemyY, 10, enemyImg));
          }
    }, 0, 5, TimeUnit.SECONDS);

    if (player.y > getHeight() - playerImg.getHeight(null)) {
        player.setY(-10);
    }
    if (player.y < 0) {
        player.setY(+10);
    }
}

public void paintComponent(Graphics g) {
    super.paintComponent(g);
    for(Enemy enemys : enemy) {
        enemys.render(g);
    }
    player.render(g);
}

首先调用tick方法,然后调用paintComponent方法。

这是输出:

Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
    at java.util.ArrayList$Itr.next(ArrayList.java:851)
    at _47b3n.spaceinvaders.framework.Main.paintComponent(Main.java:141)
    at javax.swing.JComponent.paint(JComponent.java:1053)
    at javax.swing.JComponent.paintToOffscreen(JComponent.java:5223)
    at javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:290)
    at javax.swing.RepaintManager.paint(RepaintManager.java:1265)
    at javax.swing.JComponent._paintImmediately(JComponent.java:5171)
    at javax.swing.JComponent.paintImmediately(JComponent.java:4982)
    at javax.swing.RepaintManager$4.run(RepaintManager.java:824)
    at javax.swing.RepaintManager$4.run(RepaintManager.java:807)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:807)
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:782)
    at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:731)
    at javax.swing.RepaintManager.access$1300(RepaintManager.java:64)
    at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1720)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:744)
    at java.awt.EventQueue.access$400(EventQueue.java:97)
    at java.awt.EventQueue$3.run(EventQueue.java:697)
    at java.awt.EventQueue$3.run(EventQueue.java:691)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:714)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

1 个答案:

答案 0 :(得分:2)

您似乎有两个线程,每个线程同时在ArrayList上运行。

其中一个是在事件调度线程中,其中调用了paintComponent。您正在使用增强的for循环,它在内部使用Iterator。这个迭代器正在抛出ConcurrentModificationException

当您致电ArrayList时,您正在其他线程中修改tick方法中的enemy.add(new Enemy(enemyY, 10, enemyImg));

Iterator注意到ArrayList已被修改并抛出异常。当您显示敌人时,必须具有ArrayList的一致视图。

通过在ArrayList块中的enemy封闭读写操作,在某个对象(甚至可能是ArrayList本身)上同步对此synchronized的访问。这意味着这些块中只有一个可以同时执行。

synchronized (enemy) {
    enemy.add(new Enemy(enemyY, 10, enemyImg));
}

synchronized (enemy) {
    for(Enemy enemys : enemy) {
        enemys.render(g);
    }
}