数组列表并发修改 [英] arraylist concurrent modification

查看:31
本文介绍了数组列表并发修改的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用 Java 创建一个多线程聊天.当用户 u1 向用户 u2 发送消息但用户 u2 未连接时,用户 u1 将消息发送到服务器,用户 u2 连接到服务器后将收到该消息.未发送的消息将添加到 ArrayList.用户连接后,他会检查自己是否是未决消息的接收者.如果是,则将消息发送给他,然后从待处理消息列表中删除.我是这样做的:

for(Iterator itpendingmsgs = pendingmsgs.iterator(); itpendingmsgs.hasNext();) {String pendingmsg = itpendingmsgs.next();String dest = pendingmsg.substring(4);如果(protocol.author.equals(dest)){发送消息(消息);pendingmsgs.remove(pendingmsg);}}

这是我得到的:

线程Thread-3"中的异常 java.util.ConcurrentModificationException在 java.util.AbstractList$Itr.checkForCommodification(Unknown Source)在 java.util.AbstractList$Itr.next(Unknown Source)在 ChatServer$ClientConnection.run(ChatServer.java:383)在 java.lang.Thread.run(未知来源)

我该如何解决?是因为我在使用迭代器吗?

解决方案

代替这个

pendingmsgs.remove(pendingmsg);

使用

itpendingmsgs.remove();

IteratorArrayListfail fast ,因此当您使用 Iterator 迭代 ArrayList 时,如果底层 ArrayList 被修改Iterator 本身提供的除 addremove 之外的任何方法都会抛出 ConcurrentModificationException 并退出.>

在您当前的实现中,当您在某些条件下循环列表时,您还通过在底层 ArrayList 上调用 remove 来修改列表,而不是调用 Iterator 的 remove 方法.

来自 Java 文档:

<块引用>

该类的迭代器和listIterator返回的迭代器方法是快速失败的:如果列表在任何时候在结构上被修改迭代器创建后的时间,以任何方式,除了通过迭代器自己的 remove 或 add 方法,迭代器会抛出一个并发修改异常.因此,面对并发修改,迭代器快速而干净地失败,而不是在不确定的时间冒着任意的、不确定的行为的风险未来.

请注意,不能保证迭代器的快速失败行为因为一般来说,不可能做出任何硬性保证在存在不同步的并发修改的情况下.快速失败迭代器尽最大努力抛出 ConcurrentModificationException基础.因此,编写一个依赖的程序是错误的关于这个例外的正确性:fail-fast 行为迭代器应该只用于检测错误.

I'm creating a multithread chat in java. When user u1 sends a message to user u2 but user u2 is not connected, user u1 sends the message to the server and user u2 will receive the message once he connects to the server. The messages who are not sent are added to an ArrayList. Once a user connects, he checks if he's the recipient of a pending message. If he is, the message is sent to him and then removed from the pending messages list. This is how I do it:

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);
    }
}

this is what I get:

Exception in thread "Thread-3" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
at java.util.AbstractList$Itr.next(Unknown Source)
at ChatServer$ClientConnection.run(ChatServer.java:383)
at java.lang.Thread.run(Unknown Source)

How do I fix it? Is it because I'm using the iterator?

解决方案

Instead of this

pendingmsgs.remove(pendingmsg);

use

itpendingmsgs.remove();

Iterator of ArrayList is fail fast , so while you are iterating over the ArrayList using the Iterator if underlying ArrayList is modified by any method other than add and remove provided by Iterator itself it will throw ConcurrentModificationException and will bail out.

In your current implementation while you are looping through the list on certain condition you are also modifying the list by calling remove on the underlying ArrayList, instead call remove method of the Iterator.

From the Java Docs:

The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.

Note that the fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast iterators throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs.

这篇关于数组列表并发修改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆