1

我遇到了一个我无法弄清楚的问题。如果你们能帮助我,那就太好了=)

我有一个 Lobby.Class 有一个 draw() 方法:

public void draw() {
    //USE ITERATOR TO DRAW
    Iterator<Player> itr = players.iterator();
    while(itr.hasNext()) {
        Player player = itr.next();
        int off = players.indexOf(player); //THE CORRECT HEIGHT
        player.draw(off);
    }
}  

请注意,这是一个服务器/客户端游戏

Lobby.Class 还有 1 个名为 addPlayer() 的方法

public void addPlayer(String _playerName, String _class, String _string_id) {

    int _id = Integer.parseInt(_string_id);

    //CREATE THE NEW PLAYER
    Player new_player = new Player(x, y, _id, _playerName, _class);

    //IF THIS PLAYER IS ME
    if(new_player.getID() == id) {

        me = new_player;

    } else {

        //TELL THE NEW PLAYER I EXIST
        ClientValue.getClient().iExist(_id);

                    //THIS WILL SEND TO CLIENT THAT WILL SEND TO THE SERVER
                    //THAT WILL LOOK FOR THE ID AND SEND TO CLIENT OF THAT ID
                    //AND THE CLIENT WILL SEND TO LOBBY UPDATE PLAYERS()
    }

    players.add(new_player);

    chat.appendChat(chat.joinString(_playerName, _class));
}

Lobby.Class 也有 1 个名为 updatePlayers() 的方法

public void updatePlayers(String _playerName, String _class, String _string_id) {

    //THIS IS CALLED WHEN THE SERVER TELLS THIS PLAYER
    //ABOUT OTHER PLAYERS

    int _id = Integer.parseInt(_string_id);

    //CREATE THE NEW PLAYER
    Player new_player = new Player(x, y, _id, _playerName, _class);
    players.add(new_player);

}

现在我的问题是玩家列表,当我进入大厅addPlayer()时,当 2 名玩家加入时会同时运行,或者当他们updatePlayers()一起运行时addPlayer()

我得到的异常是:ConcurrentModificationException

我缺少两种方法,1 用于添加带有 Iterator 的玩家(如果可能),1 用于删除玩家。这样我就不会在通过它或添加/删除它时收到修改玩家列表的错误。

我曾尝试过使用 Iteror 和 ListIterator,但由于我以前从未使用过它们,所以我不知道该怎么做。我需要一些关于如何做到这一点的建议。非常感谢提前=)

解决方案:

private List<Player> players = Collections.synchronizedList(new ArrayList<Player>());

    public synchronized void playersList(String cmd, Player _player) {

    Iterator<Player> itr = players.iterator();

    if(cmd.equals("draw")) {

        while(itr.hasNext()) {

            Player player = itr.next();
            int off = players.indexOf(player);
            player.draw(off);
        }

    } else if(cmd.equals("add")) {

        players.add(_player);

    } else if(cmd.equals("remove")) {

        players.remove(_player);
    }
}
4

1 回答 1

1

您需要同步访问列表,一次只允许一个线程访问列表。

您可以synchronized在每个访问点周围使用一个块(包括整个绘制方法),或者您可以使用 player 方法将播放器列表包装在线程安全列表中,Collections#synchronizedList或者代替迭代器,您可以使用playertoArray方法

Player[] arrayOfPlayers = players.toArray(new Player[players.size()]);

您仍然要synchronized拨打此电话,但您只锁定了一行,而不是整个循环

于 2012-10-20T20:11:13.770 回答