0

そこで、LWJGL を使用して単純な重力を作成しようとしていますが、java.util.ConcurrentModificationException例外が発生してアプリケーションがランダムにクラッシュします。奇妙なことは、それが常に同時に起こるとは限らないということです。すぐにクラッシュすることもありますが、クラッシュする前に 10 分間問題なく動作することもあります。

メインゲームクラス:

public static ArrayList<Block> blocks;

public Game() {
    blocks = new ArrayList<Block>();

    for(int i = 0; i < 40; i++)
        blocks.add(new BlockTest(i, 21, new float[] {0.4f, 0.6f, 0.7f}, false, 0));

    spawnTimer.scheduleAtFixedRate(new TimerTask() {
          public void run() {
              spawnBlock();
          }
    }, 1000, 1000);
}
public void update() {
    for(Block b : blocks)
        b.update();
}

ブロッククラス:

/** Update block */
public void update() {
    if(hasGravity) {
        boolean colliding = false;

        for(Block b : Game.blocks)
            if(b.getBlockID() == 0) {
                if(Util.checkBlockCollision(this, b)) {
                    colliding = true;
                    setBlockID(0);
                }
            }

        if(fallDelay.over() && !colliding) {
            setBlockYPosWithoutBlockSize(y += 2);
            fallDelay.start();
        }
    }
}

スタック トレースは次のとおりです。

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
    at java.util.ArrayList$Itr.next(Unknown Source)
    at snakybo.gravitytest.block.Block.update(Block.java:26)
    at snakybo.gravitytest.Game.update(Game.java:34)
    at Main.gameLoop(Main.java:52)
    at Main.main(Main.java:21)

(Game.java:34) は次の行です。

b.update();

そして (Block.java:26) は:

for(Block b : Game.blocks)

完全なコードが必要な場合は、Githubで入手できます

4

1 に答える 1

4

あなたはマルチスレッドです。TimerTask は別のスレッドで実行されます。

何が起こるか: タイマー タスク スレッドで呼び出されている spawnBlock メソッドが、ブロック リストを変更します (リストに 1 つ追加します)。メイン スレッドで update メソッドが呼び出され、コードがブロック リストを反復処理します。

その反復中 (他のスレッドでの spawnblock メソッドの実行中) にブロックがブロック リストに追加されるため、concurrentModificationException が発生します。

「for(Block b : blocks)」を「for(Block b : new ArrayList(blocks))」に置き換えるのは非常に単純ですが、それほどパフォーマンスの高いソリューションではありません。常に新しいコピーを反復処理するため、元のリストを次のように変更できます。好きなだけ。

より良い解決策は、メソッドを同期化するか、ブロック リストを同期化されたラッパーでラップするなど、設計を再考することです。

于 2013-05-04T12:28:54.733 に答える