Java arraylist并发修改

Java arraylist并发修改,java,arraylist,iterator,concurrentmodification,Java,Arraylist,Iterator,Concurrentmodification,我正在用java创建一个多线程聊天。当用户u1向用户u2发送消息但用户u2未连接时,用户u1将消息发送到服务器,用户u2将在连接到服务器后接收消息。未发送的邮件将添加到ArrayList中。一旦用户连接,他会检查自己是否是挂起邮件的收件人。如果他是,则将消息发送给他,然后从挂起消息列表中删除。我就是这样做的: for(Iterator<String> itpendingmsgs = pendingmsgs.iterator(); itpendingmsgs.hasNext();) {

我正在用java创建一个多线程聊天。当用户u1向用户u2发送消息但用户u2未连接时,用户u1将消息发送到服务器,用户u2将在连接到服务器后接收消息。未发送的邮件将添加到ArrayList中。一旦用户连接,他会检查自己是否是挂起邮件的收件人。如果他是,则将消息发送给他,然后从挂起消息列表中删除。我就是这样做的:

for(Iterator<String> itpendingmsgs = pendingmsgs.iterator(); itpendingmsgs.hasNext();) {
    String pendingmsg = itpendingmsgs.next();
    String dest = pendingmsg.substring(4);              
    if (protocol.author.equals(dest)) {
        sendMsg(msg);
        pendingmsgs.remove(pendingmsg);
    }
}
我怎么修理它?是因为我使用的是迭代器吗?

而不是这个

pendingmsgs.remove(pendingmsg);
使用

数组列表的
迭代器
,因此,当您使用
迭代器
数组列表
上迭代时,如果底层
数组列表
迭代器
本身提供的
添加
删除
以外的任何方法修改,它将抛出
ConcurrentModificationException
,并退出

在当前的实现中,当您在特定条件下循环列表时,您还可以通过在基础
ArrayList
上调用
remove
来修改列表,而不是调用
迭代器的
remove
方法

从Java文档:

此类的迭代器和listIterator返回的迭代器 方法是快速失败的:如果列表在任何时候进行了结构修改 创建迭代器后的时间,以任何方式,除了通过 迭代器自己的remove或add方法,迭代器将抛出 ConcurrentModificationException。因此,面对同时发生的冲突, 修改后,迭代器会快速、干净地失败,而不是 在不确定的时间冒任意、不确定行为的风险 将来

请注意,无法保证迭代器的快速失败行为 一般来说,不可能作出任何硬性保证 在存在非同步并发修改的情况下。快速失败 迭代器尽最大努力抛出ConcurrentModificationException 基础。因此,编写依赖于 关于其正确性的例外:的fail fast行为 迭代器只能用于检测bug

而不是这个

pendingmsgs.remove(pendingmsg);
使用

数组列表的
迭代器
,因此,当您使用
迭代器
数组列表
上迭代时,如果底层
数组列表
迭代器
本身提供的
添加
删除
以外的任何方法修改,它将抛出
ConcurrentModificationException
,并退出

在当前的实现中,当您在特定条件下循环列表时,您还可以通过在基础
ArrayList
上调用
remove
来修改列表,而不是调用
迭代器的
remove
方法

从Java文档:

此类的迭代器和listIterator返回的迭代器 方法是快速失败的:如果列表在任何时候进行了结构修改 创建迭代器后的时间,以任何方式,除了通过 迭代器自己的remove或add方法,迭代器将抛出 ConcurrentModificationException。因此,面对同时发生的冲突, 修改后,迭代器会快速、干净地失败,而不是 在不确定的时间冒任意、不确定行为的风险 将来

请注意,无法保证迭代器的快速失败行为 一般来说,不可能作出任何硬性保证 在存在非同步并发修改的情况下。快速失败 迭代器尽最大努力抛出ConcurrentModificationException 基础。因此,编写依赖于 关于其正确性的例外:的fail fast行为 迭代器只能用于检测bug


除了通过
迭代器
实例本身之外,不允许在遍历列表时修改列表。您必须调用
itpendingmsgs.remove()

在遍历列表时,不允许修改列表,除非通过
迭代器
实例本身。您必须调用
itpendingmsgs.remove()
而不是

pendingmsgs.remove(pendingmsg);
使用

见:

如果基础的 在迭代以任何方式进行时修改集合 而不是通过调用此方法

来源:

而不是

pendingmsgs.remove(pendingmsg);
使用

见:

如果基础的 在迭代以任何方式进行时修改集合 而不是通过调用此方法


来源:

根据文档,此类迭代器和listIterator方法返回的迭代器故障很快:如果在迭代器创建后的任何时间,以迭代器自己的remove或add方法以外的任何方式对列表进行结构修改,迭代器将抛出ConcurrentModificationException

在迭代集合时,不应将其从集合中删除。您应该改用迭代器的remove方法

for(Iterator<String> itpendingmsgs = pendingmsgs.iterator(); itpendingmsgs.hasNext();) {
String pendingmsg = itpendingmsgs.next();
String dest = pendingmsg.substring(4);              
if (protocol.author.equals(dest)) {
    sendMsg(msg);
    itpendingmsgs.remove();
}
for(迭代器itpendingmsgs=pendingmsgs.Iterator();itpendingmsgs.hasNext();){
字符串pendingmsg=itpendingmsgs.next();
字符串dest=pendingsg.substring(4);
if(协议作者等于(目的地)){
sendMsg(msg);
itpendingmsgs.remove();
}

}

根据文档,此类迭代器和listIterator方法返回的迭代器故障很快:如果在迭代器创建后的任何时间,以迭代器自己的remove或add方法以外的任何方式对列表进行结构修改,迭代器将抛出ConcurrentModificationException

在迭代集合时,不应将其从集合中删除。您应该改用迭代器的remove方法
for(Iterator<String> itpendingmsgs = pendingmsgs.iterator(); itpendingmsgs.hasNext();) {
String pendingmsg = itpendingmsgs.next();
String dest = pendingmsg.substring(4);              
if (protocol.author.equals(dest)) {
    sendMsg(msg);
    itpendingmsgs.remove();
}