Pergunta

I have encountered a problem that I cannot quite figure out. Would be super if you guys could help me out =)

I have a Lobby.Class that has a draw() Method:

public void draw() {
    //USE ITERATOR TO DRAW
    Iterator<Player> itr = players.iterator();
    while(itr.hasNext()) {
        Player player = itr.next();
        int off = players.indexOf(player); //THE CORRECT HEIGHT
        player.draw(off);
    }
}  

Note that this is a server/client game

The Lobby.Class has also 1 method called addPlayer()

public void addPlayer(String _playerName, String _class, String _string_id) {

    int _id = Integer.parseInt(_string_id);

    //CREATE THE NEW PLAYER
    Player new_player = new Player(x, y, _id, _playerName, _class);

    //IF THIS PLAYER IS ME
    if(new_player.getID() == id) {

        me = new_player;

    } else {

        //TELL THE NEW PLAYER I EXIST
        ClientValue.getClient().iExist(_id);

                    //THIS WILL SEND TO CLIENT THAT WILL SEND TO THE SERVER
                    //THAT WILL LOOK FOR THE ID AND SEND TO CLIENT OF THAT ID
                    //AND THE CLIENT WILL SEND TO LOBBY UPDATE PLAYERS()
    }

    players.add(new_player);

    chat.appendChat(chat.joinString(_playerName, _class));
}

The Lobby.Class has also 1 method called updatePlayers()

public void updatePlayers(String _playerName, String _class, String _string_id) {

    //THIS IS CALLED WHEN THE SERVER TELLS THIS PLAYER
    //ABOUT OTHER PLAYERS

    int _id = Integer.parseInt(_string_id);

    //CREATE THE NEW PLAYER
    Player new_player = new Player(x, y, _id, _playerName, _class);
    players.add(new_player);

}

Now my problem is the players List, when I enter the lobby addPlayer() will Run at the same time when 2 players join, or when the updatePlayers() are run with addPlayer()

The Exception i get is: ConcurrentModificationException

I am missing two methods, 1 for adding players with an Iterator if possible, 1 for removing players. So that I wont get the error for modifying the players List while going trough it or adding/removing it.

I have tried puzzling around with Iteror and ListIterator, but as I have never used them before, I am not sure what to do. I need some advice on how to do this. Many thanks in advance =)

Solution:

private List<Player> players = Collections.synchronizedList(new ArrayList<Player>());

    public synchronized void playersList(String cmd, Player _player) {

    Iterator<Player> itr = players.iterator();

    if(cmd.equals("draw")) {

        while(itr.hasNext()) {

            Player player = itr.next();
            int off = players.indexOf(player);
            player.draw(off);
        }

    } else if(cmd.equals("add")) {

        players.add(_player);

    } else if(cmd.equals("remove")) {

        players.remove(_player);
    }
}
Foi útil?

Solução

You need to synchronise access to the list, allowing only one thread to access the list at a time.

You could use a synchronized block around each access point (including the entire paint method) or you could wrap the player list in a thread safe list using Collections#synchronizedList or, instead of an iterator, you could use the toArray method of players

Player[] arrayOfPlayers = players.toArray(new Player[players.size()]);

You are still going to synchronized the this call, but your only locking one line, not a whole loop

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top