2014-10-01 76 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是 “游戏” 里面Lobby.java的空ArrayList。通过其他功能添加游戏。

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

如果您使用迭代器,则只能更改对象。 – 2014-10-01 02:49:02

+0

1,我已经尝试过使用迭代器。其次,我不修改任何没有使用迭代器的函数。 – anonmous 2014-10-01 02:50:29

+1

'Lobby.removeGame(g);'表示您在循环中篡改'Lobby.games'。 – njzk2 2014-10-01 02:56:40

回答

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 2014-10-01 03:03:05

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(),要么保存循环后要移除的游戏集合,要么重新组织代码以避免这种情况。

相关问题