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);
}
}
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 usingCollections#synchronizedList
or, instead of an iterator, you could use thetoArray
method of playersYou are still going to
synchronized
the this call, but your only locking one line, not a whole loop