2016-11-28 79 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

相关问题