Java arraylist并发修改
我正在用java创建一个多线程聊天。当用户u1向用户u2发送消息但用户u2未连接时,用户u1将消息发送到服务器,用户u2将在连接到服务器后接收消息。未发送的邮件将添加到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();) {
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();
}