2014-10-01 75 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(),要麼保存循環後要移除的遊戲集合,要麼重新組織代碼以避免這種情況。

相關問題