2016-11-28 78 views
-2

我正在使用Java創建在線視頻遊戲。 如果有客戶端和服務器應用程序。 在服務器中,爲了處理玩家數據庫,我創建了一個名爲inGamePlayers的ArrayList,其中包含Players對象(使用InetAdress的ipAdress和String用戶名)。Java ConcurrentModificationException與ArrayList

當玩家連接時,它首先檢查連接的玩家用戶名==是否與ArrayList用戶名中的一個玩家有關。如果不是,則將其添加到列表中。否則,連接播放器被認爲是'重新連接'...

當它在Eclipse上運行時,它的工作很奇怪。所以我決定把代碼的一部分作爲「Java Tutor」中的一個測試(它是一個讀取代碼並向您顯示變量的網站,在開始編程時非常方便)。

在第一

for (Player p : inGamePlayers) { 

線,它停止並說java.util.ConcurrentModificationException,而不是第一,但它傳遞-由第二時間。

這裏是我的整個測試代碼

import java.util.ArrayList; 

public class YourClassNameHere { 

    public static void main(String[] args) { 

     ArrayList<Player> inGamePlayers = new ArrayList<Player>(); 
     inGamePlayers.add(new Player("Griff")); 

     String newUsername = "Polak"; 

     for (Player p : inGamePlayers) { 

      if (newUsername == p.username) { 
       System.out.println(p.username+" reconnected!"); 
       break; 
      } 

      inGamePlayers.add(new Player(newUsername)); 
     } 

     for (Player p : inGamePlayers) { 
      System.out.println(p.username); 
     } 
    } 
} 

class Player { 

    public String username; 

    public Player(String username) { 
     this.username = username; 
    } 
} 
+2

你能請張貼整個'for'循環。很明顯,錯誤不僅來自該行。 – Mat

+0

如果您在迭代過程中修改集合,那麼對常規集合的迭代會爆炸並出現ConcurrentModificationException異常。簡單修復:使用'Set'(如'HashSet'),不檢查,只需添加 - 該設置將確保沒有重複。這個「洞察」在javadoc中都是可用的。 – Bohemian

+0

@ΦXocę웃PepeúpaツOP甚至不需要多個線程 - AFAICT他正在循環中添加 – Bohemian

回答

3

該代碼有多種缺陷。在這種形式下,它將添加新的播放器實例,直到找到具有匹配名稱的條目。按照您的觀察,開始迭代,修改列表並繼續迭代將引發ConcurrentModificationException。此外,您將字符串與==而不是equals進行比較。

for (Player p : inGamePlayers) { 

    if (newUsername == p.username) { // This needs to be .equals 
     System.out.println(p.username+" reconnected!"); 
     break; 
    } 
    // this line runs many times 
    inGamePlayers.add(new Player(newUsername)); 
    } 

相反,我建議你提取代碼到一個新的功能,並更改控制流程:

private static void handleConnected(ArrayList<Player> inGamePlayers, String newUsername) { 
    for (Player p : inGamePlayers) { 
    if (newUsername.equals(p.username)) { 
     System.out.println(p.username+" reconnected!"); 
     return; // return instead of break 
    } 
    } 
    // we did not return, so this user is new 
    inGamePlayers.add(new Player(newUsername)); 
} 

// ... 

public static void main(String[] args) { 
    ArrayList<Player> inGamePlayers = new ArrayList<Player>(); 
    inGamePlayers.add(new Player("Griff")); 

    String newUsername = "Polak"; 

    // Call this function in place of the old loop 
    handleConnected(inGamePlayers, newUsername); 

    for (Player p : inGamePlayers) { 
    System.out.println(p.username); 
    } 
} 
+0

謝謝你的替代解決方案! @PravinSonawane是正確的,我不能修改我的ArrayList,而迭代它 – GriffinBabe

相關問題