简体   繁体   中英

Java - Modifying Tile set in render and tick method

I have a method for rendering and one for ticking worlds. Because they sometimes run at the same time I'm getting a ConcurrentModificationException while looping over the Tiles.

public void render(Graphics gfx)
{
    bounds.setLocation(getEdgeX(), getEdgeY());

    for(Tile tile : tiles)
    {
        if(bounds.intersects(tile.getBounds()))
        {
            activeTiles.add(tile);
            tile.render(gfx);
        }
    }

    translate(gfx);
    int x = platformer.getX() - platformer.getX() % background.getWidth();
    gfx.drawImage(background, x, 0, null);
    gfx.drawImage(background, x + Platformer.SCREEN_SIZE.width, 0, null);
    platformer.render(gfx);
}

public void tick()
{
    platformer.tick();

    for(Tile tile : activeTiles) //Exception
    {
        if(tile instanceof AdvancedTile)
        {
            ((AdvancedTile)tile).tick();
        }
    }
}

Exception

Exception in thread "main" java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:926)
at java.util.HashMap$KeyIterator.next(HashMap.java:960)
at me.lordal.platformer.world.World.tick(World.java:59)
at me.lordal.platformer.world.WorldManager.tickCurrentWorld(WorldManager.java:55)
at me.lordal.platformer.screens.GameScreen.tick(GameScreen.java:41)
at me.lordal.platformer.screens.CardHandler.tick(CardHandler.java:60)
at me.lordal.platformer.Platformer.update(Platformer.java:65)
at me.lordal.platformer.Platformer.run(Platformer.java:53)
at me.lordal.platformer.Platformer.main(Platformer.java:25)

As you can see the render method has a part where it adds tiles to the set, while the ticking method has a Tile loop aswell.

How can I fix this?

Since I don't see any "change-on-iteration" code, I suspect the problem here is about concurrency.

Two methods cannot overlap execution unless they are invoked by different threads.

If this is your case, you could make them syncronized on the object's lock:

public synchronized void render(Graphics gfx) {
    // ...
}
public synchronized void tick() {
    // ...
}

While subsequent calls will need to wait for previous invocations to finish execution, this may reduce performance.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM