0

I am developing a multi-player snake game played over the network. It is running fine however it occasionally throws java.util.ConcurrentModification Exception. This is thrown in the main class of my game in the paintComponent() method. Code at which this is thrown is

 for (String name : map.keySet()) {
        if (!map.get(name).gameover) {
            for (int i = 0; i < map.get(name).length; i++) {
                rect = new Rectangle2D.Double(map.get(name).p[i].x,
                        map.get(name).p[i].y, width, width);
                g1.setColor(Color.black);
                g1.draw(rect);
                g1.setPaint(map.get(name).snakecolor);
                g1.fill(rect);
            }
        }
    }

The Hashmap map is a mapping from

        HashMap<String,Snake> 

where Snake is the class which has all the attributes of a snake. The main class also runs a thread side by side for receiving messages and updates from other clients through the server.

The iterator on the thread side also uses the same map(passed by reference to that class). Code for that is as given below. This function is called if the score of any player reaches some specific point after which the level is upgraded.

    void levelUp(int level){
    for(String name:map.keySet()){
        map.get(name).level=level;
    }
    Game.speed=100/level;
}

I think the clash between object write is due to this. Can anyone please suggest a solution for this problem.

The Code where I put values into the map is also given below.

void populateMap() {
    try {
        try {
            objin = new ObjectInputStream(socket.getInputStream());
        } catch (StreamCorruptedException e) {
            System.out.println("Stream Corrupted!");
        }
        Object name = objin.readObject();
        if (((Snake) name).player.equals("food_coord")) {
            Game.foodx = objin.readInt();
            Game.foody = objin.readInt() + 35;
            start = true;
            System.out.println("Game Started");
            return;
        } else {
            map.put(((Snake) name).player, (Snake) name);
            System.out.println("Recieved: " + ((Snake) name).player);
        }
    } catch (java.net.SocketException s) {
        JOptionPane.showMessageDialog(null, "Server Closed", "ERROR",
                JOptionPane.ERROR_MESSAGE);
        System.exit(0);
    } catch (Exception e) {
        e.printStackTrace();
    }
}
Sohaib
  • 4,556
  • 8
  • 40
  • 68
  • using entrySet() in place of keySet() will optimize your code. – Aubin Apr 13 '13 at 08:52
  • Where is `map` changed (`put` or `remove` called)? – acdcjunior Apr 13 '13 at 08:53
  • That is at the initiation of the thread I will post that code above. Although in this case that part is not taking in concurrency since the paintComponent runs only after initiation has been completed – Sohaib Apr 13 '13 at 09:22
  • Chances are this `populateMap()` is being called when `map` is being iterated (that's the most common cause of `ConcurrentModificationException`). Can you also post the exception stacktrace? (And point which line is the last line executed.) Will help a lot. – acdcjunior Apr 13 '13 at 09:46
  • When the populateMap() is done then no iterations on the map are done. A variable recievedfrom the server side triggers populateMap to be stopped and map iterations (that receive and update data) to begin. SO I dont think theres a clash there. – Sohaib Apr 13 '13 at 09:56

1 Answers1

1

Change your map implementation class to one that support concurrency such as ConcurrentHashMap

Ori Dar
  • 18,687
  • 5
  • 58
  • 72
  • 2
    May solve the problem, but I must point out it is not guaranteed: [Note that `ConcurrentModificationException` does not always indicate that an object has been concurrently modified by a _different_ thread.](http://docs.oracle.com/javase/1.5.0/docs/api/java/util/ConcurrentModificationException.html) – acdcjunior Apr 13 '13 at 09:05