Search code examples
javamultithreadingarraylistserverconcurrentmodification

ConcurrentModificationException in multithreaded Java application


I have the following problem: We are doing multithreaded game and there is a Server which extends Thread and is the host of the game, as well there is a GameUpdater which also extends Thread and is a prototype of game engine. The problem is that GameUpdater adds and removes some object to the game, while Server sends to Client all updates (example given below):

private void sendUpdatedAsteroids() {
        Collection<Asteroid> asteroids = this.game.getAsteroids();
        StringBuilder existentAsteroids = new StringBuilder();
        for(Asteroid asteroid : asteroids) {
            if (!asteroid.isDestroyed()) {
                existentAsteroids.append(asteroid.getUniqueID());
                existentAsteroids.append("@");

                Message message = new Message();
                message.encryptObject(asteroid);
                try {
                    this.sendMessage(message);
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                }
            }
        }


        Message message = new Message(MessageType.GENERAL, existentAsteroids.toString());
        try {
            sendMessage(message);
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }

The following error always occurs:

    at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1042)
    at java.base/java.util.ArrayList$Itr.next(ArrayList.java:996)

I think that the problem is that GameUpdater removes and adds objects, and then Server tries to send to Client non-existing objects. The solution to the problem was found: making copy of asteroids and then send it to Client, but the problem is that it takes a lot of memory. Any other solutions are appreciated (for example make two different threads working together).


Solution

  • If element updates in list (add/remove) is less frequent compare to Iteration, I would suggest to consider CopyOnWriteArrayList. Unless frequent write is involved, It is efficient for safe iteration.

    Otherwise Collections.SynchronizedList could be used with synchronized block over iteration of the list. This will cause the other thread to wait till iteration completes