ArrayList的并发修改 [英] arraylist concurrent modification

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

问题描述

我创建在Java多线程聊天。当用户U1将消息发送到用户U2但用户U2没有连接,用户U1将消息发送到服务器和用户U2一旦他连接到服务器将接收该消息。谁不发送的信息被添加到一个ArrayList。一旦用户连接,他检查,如果他是一个未决的邮件的收件人。如果他是,该消息被发送给他,然后取出从未决消息列表。这就是我如何做到这一点:

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

这是我所得到的:

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?

推荐答案

取而代之的是

pendingmsgs.remove(pendingmsg);

使用

itpendingmsgs.remove();

的Iterator 的ArrayList 快速失败 ,所以当你在遍历的ArrayList 使用的Iterator ,如果底层的ArrayList 是比添加及修改删除迭代器提供本身就会抛出 ConcurrentModificationException的,将保释出去。

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.

在你当前的实现,而你是通过一定的条件下,你也修改列表中的列表,通过调用删除于底层的ArrayList <循环/ code>,而不是叫删除的方法的Iterator

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.

从Java文档:

此类的迭代器的ListIterator和返回的迭代器
  方法是快速失败的:如果列表结构的任何修改
  迭代器后时间被创建,以任何方式,除了通过
  迭代器自身的移除或添加方法,迭代器都将抛出
  ConcurrentModificationException的。因此,在并行的面
  修改,迭代器很快就会完全失败,而不是
  在一个不确定的时间任意冒险,不确定性的行为
  在未来的。

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.

请注意,迭代器的快速失败行为不能得到保证
  因为它是,一般来说,不可能作出任何硬性保证
  不同步并发修改的presence。快速失败
  迭代器扔在尽最大努力ConcurrentModificationException的
  基础。因此,这将是错误的编写依赖程序
  于此异常它的正确性:的快速失败行为
  迭代器应该仅用于检测bug。

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.

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

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