2014-10-01 3 views
0

В настоящее время я программирую многопользовательскую игру на Java. Мой текущий код (который получает ошибку) так же.ConcurrentModificationException, но без изменений

@Override 
public void onClose(WebSocket conn, int code, String reason, boolean remote){ 
    System.out.println("Socket disconnected."); 

    for(Game g : Lobby.games){ 
     if(g.hasPlayer(new Player(conn))){ 
      Player ourPlayer = null; 

      for(Player p : g.getPlayers()){ 
       if(p.getSocket() == conn){ 
        ourPlayer = p; 
        break; 
       } 
      } 

      if(ourPlayer == null) return; 

      g.removePlayer(ourPlayer); 

      for(Player p : g.getPlayers()){ 
       send(p.getSocket(), Messages.SEND_REMOVE_PLAYER + ourPlayer.getName()); 
      } 

      if(g.getPlayers().size() == 0){ 
       Lobby.removeGame(g); 
      } 
     } 
    } 
} 

Теперь, пожалуйста, не спрашивайте о таких функциях, как onClose. Это не вызывает проблемы.

Я получаю ConcurrentModificationException следующую строку:

for(Game g : Lobby.games){ 

Lobby.games является пустой ArrayList из "игры" внутри Lobby.java. Игры дополняются другими функциями.

public static ArrayList<Game> games = new ArrayList<Game>(); 

UPDATE: И это removeGame:

public static void removeGame(Game game){ 
    Iterator<Game> itr = games.iterator(); 

    while(itr.hasNext()){ 
     Game g = itr.next(); 

     if(g.getId() == game.getId()){ 
      System.out.println("Game "+g.getId()+" removed"); 
      itr.remove(); 
     } 
    } 
} 

Извините за размытости. Если вам нужен еще один код, я обязательно добавлю его. Благодаря!

+0

Вы можете изменить объект, только если вы используете итератор. –

+0

1st, я уже пробовал использовать итератор. Во-вторых, я ничего не изменяю без функций, которые используют Итераторы. – anonmous

+1

'Lobby.removeGame (g);' предполагает, что вы пытаетесь манипулировать 'Lobby.games' в цикле. – njzk2

ответ

0

Ваш вызов Lobby.removeGame(g) означает, что вы намерены изменить список, несмотря на то, что вы выполняете его прямо сейчас, что полностью аннулирует неявное упорядочение.

Если вам нужно сделать это, используйте явную обратную петлю, так что вы только изменение части списка, которые не будут влиять на порядок частей вы еще не дошли до еще:

for(int i=Lobby.games.size()-1; i>-1; i--) { 
    Game g = Lobby.games.get(i); 

    // this is now safe, because you're only ever going to see 
    // indices lower than the current "i", and the removal 
    // only how long Lobby.games is *after* "i", not before it. 
    Lobby.games.remove(g) 
} 
+0

Спасибо вам большое! – anonmous

2

Ваша проблема (почти наверняка) здесь:

for(Game g : Lobby.games) { 
    // other code 
    if (g.getPlayers().size() == 0){ 
     Lobby.removeGame(g); 
    } 
} 

если Lobby.removeGame(g) изменяет содержание Lobby.games, то вы будете изменять Lobby.games во время прохода над ним (цикл foreach неявно перебирает Lobby.games).

Либо используйте итератор и позвоните Iterator.remove(), либо сохраните коллекцию игр, которые нужно удалить после цикла, или иным образом реорганизовать ваш код, чтобы избежать этой ситуации.

Смежные вопросы