Java 迭代器、列表迭代器和列表

Java 迭代器、列表迭代器和列表,java,list,iterator,listiterator,Java,List,Iterator,Listiterator,我遇到了一个我不太明白的问题。 如果你们能帮我就好了=) 我有一个Lobble.Class,它有一个draw()方法: 类还有一个名为updatePlayers()的方法 现在我的问题是players列表,当我进入大厅时addPlayer()将在两名玩家加入时同时运行,或者当updatePlayers()与addPlayer()一起运行时 我得到的例外是:ConcurrentModificationException 我缺少两种方法,一种是使用迭代器添加玩家,一种是删除玩家。这样我就不会因为修改

我遇到了一个我不太明白的问题。 如果你们能帮我就好了=)

我有一个Lobble.Class,它有一个draw()方法:

类还有一个名为updatePlayers()的方法

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

我得到的例外是:ConcurrentModificationException

我缺少两种方法,一种是使用迭代器添加玩家,一种是删除玩家。这样我就不会因为修改球员名单或添加/删除球员名单而出错

我尝试过使用ItError和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);
    }
}
private List players=Collections.synchronizedList(new ArrayList());
公共同步无效播放器列表(字符串cmd,播放器\u播放器){
迭代器itr=players.Iterator();
如果(命令等于(“绘制”)){
while(itr.hasNext()){
Player=itr.next();
int off=玩家。indexOf(玩家);
球员平局;
}
}else if(cmd.equals(“add”)){
players.add(_player);
}else if(cmd.equals(“remove”)){
玩家。移除(_玩家);
}
}

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

您可以在每个访问点周围使用
synchronized
块(包括整个绘制方法),或者可以使用播放器的
toArray
方法而不是迭代器将播放器列表包装在线程安全的列表中

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

您仍然要进行此调用的
同步
线程,但您只锁定了一行,而不是整个循环

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

您可以在每个访问点周围使用
synchronized
块(包括整个绘制方法),或者可以使用播放器的
toArray
方法而不是迭代器将播放器列表包装在线程安全的列表中

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

您仍然要进行
synchronized
this调用,但您只锁定了一条线路,而不是整个循环

该类的迭代器和listIterator方法返回的迭代器是快速失效的:如果在迭代器创建后的任何时候以任何方式(除迭代器自己的remove或add方法外)修改列表的结构,迭代器将抛出ConcurrentModificationException。“。您无法避免它,。好吧,但是如果我在类的顶部初始化一个迭代器,然后使用该迭代器添加和删除,会怎么样呢。我还注意到迭代器没有add方法,这是否意味着我必须使用ListIterator?您已经看到了您的链接,我会看看是否找到了解决方案。要避免抛出
ConcurrentModificationException
,请使用迭代器自己的方法。如果您使用
List
remove()
方法,异常将一直抛出,对我来说,我总是使用
ListIterator
。清除内容的方法很多=)将尝试并发回该类的迭代器和listIterator方法返回的迭代器是快速失效的:如果在迭代器创建后的任何时候以任何方式(除迭代器自己的remove或add方法外)修改列表的结构,迭代器将抛出ConcurrentModificationException。“。您无法避免它,。好吧,但是如果我在类的顶部初始化一个迭代器,然后使用该迭代器添加和删除,会怎么样呢。我还注意到迭代器没有add方法,这是否意味着我必须使用ListIterator?您已经看到了您的链接,我会看看是否找到了解决方案。要避免抛出
ConcurrentModificationException
,请使用迭代器自己的方法。如果您使用
List
remove()
方法,异常将继续抛出,对我来说,我总是使用
ListIterator
。清除内容的方法很多=)将尝试该方法并返回OK,非常感谢。但是与lobble.Class对话的唯一线程是Client.Class。所以只有一个线程,我还需要同步还是使用线程安全列表?sry来回答所有问题。实际上,看起来有两个线程正在访问您的列表,否则您不会出现并发修改异常。在迭代列表时不能更改它。您需要同步访问,以便更新或迭代访问,而不是同时更新或迭代访问。在这种情况下,为什么不使用CopyOnWriteArrayList?@Mik378不错的主意(我今天学到了一些东西),它确实会增加很多开销,
synchroniedList
会更快吗???@MadProgrammer如果你写得少,读得多,CopyOnWriteArraylist就完美了。相反,如果写操作非常频繁,那么由于潜在的巨大arraycopy使用量,性能就会降低。因此可以有效地使用synchronizedList。不管怎样,没有测试什么都做不了:)好的,非常感谢。但是与lobble.Class对话的唯一线程是Client.Class。所以只有一个线程,我还需要同步还是使用线程安全列表?sry来回答所有问题。实际上,看起来有两个线程正在访问您的列表,否则您不会出现并发修改异常。在迭代列表时不能更改它。您需要同步访问,以便更新或迭代访问,而不是同时更新或迭代访问。在这种情况下,为什么不使用CopyOnWriteArrayList?@Mik378好主意(我今天学到了一些东西),它确实会增加很多开销,是不是同步
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);
    }
}
Player[] arrayOfPlayers = players.toArray(new Player[players.size()]);