ConcurrentModificationException的;无法修复

时间:2014-02-22 14:14:40

标签: java oop minecraft bukkit concurrentmodification

我正在开发一个名为Bukkit的游戏服务器api的插件;这个插件允许玩家玩迷你游戏 - 游戏中的游戏。

我面临的问题是停止比赛。当游戏停止时,它会循环播放该游戏中的所有玩家,然后将其删除。问题是,当移除播放器时,它们将从竞技场列表中删除。这个竞技场列表正在循环播放;导致ConcurrentModificationException。

这是我的代码:

ArrayList<String> players = new ArrayList<String>(arena.getPlayers());        
for(String player : players){
    removePlayer(Bukkit.getPlayer(player));
}

在removePlayer函数中,正在从arena.getPlayers()中删除播放器。

任何帮助都将不胜感激。

编辑:这是github回购https://github.com/MCMedia/GunGames/blob/master/src/com/ViralAftermath/GunGame/Arena/ArenaManager.java

3 个答案:

答案 0 :(得分:1)

当你对它进行迭代时,你无法从ArrayList中删除它。

您应该更改代码以使用Iterator,然后调用.remove()

这样的东西
 Iterator <String> it = players.iterator ();
 while (it.hasNext ()) it.remove ();

它将从玩家中删除所有项目。但是你可以使用更好的方法来清除数组。

它将解决您的问题,当然您应该将此示例调整为您的真实代码。但是当您从正在读取它的ArrayList中删除项目时会导致该问题。您应该使用适当的.remove项或使用索引..

答案 1 :(得分:1)

要在迭代时从ArrayList移除项目,您必须使用Iterator.remove()。将代码更改为

  ArrayList<String> players = new ArrayList<String>(arena.getPlayers());         
  Iterator playersIterator =  players.iterator();
    while(playersIterator.hasNext()){
        playersIterator.remove();
    }

这不会抛出ConcurrentModificationException。希望这有帮助!

  

文档说明当线程在使用失败快速迭代器迭代集合时直接修改集合时,迭代器将抛出此异常。这种情况发生在你的情况下。

答案 2 :(得分:0)

感谢您的答案..修复它:

             int place = 0;
             ArrayList<String> players = new ArrayList<String>(arena.getPlayers());         
             Iterator<String> playersIterator =  players.iterator();
             while(playersIterator.hasNext()){
                 place ++;
                 Player player = Bukkit.getPlayer(playersIterator.next());
                 player.getInventory().setArmorContents(null);
                 player.getInventory().clear();
                 player.setHealth(player.getMaxHealth());
                 player.setFireTicks(0);
                 player.teleport(arena.getLobby());
                 arena.sendMessage(ChatColor.BLUE + player.getName() + " has left the Arena! There are " + arena.getPlayers().size() + " players currently left!");
                 player.getInventory().setContents(inv.get(player.getName()));
                 player.getInventory().setArmorContents(armour.get(player.getName()));
                 Bukkit.broadcastMessage(arena.getPlayers().toString());
                 playersIterator.remove();
                 if(place == arena.getPlayers().size()){
                     arena.getPlayers().clear();
                 }
             }