1

我有一个静态方法,我从 doInBackGround() 中的 Asynctask 调用

在方法中有这部分代码:

    ArrayList<Message> messagesList = new ArrayList<Message>();
    if (!clearList) {
        messagesList.addAll(messages.getMessagesList());
            for (Message msg : messagesList) {
                if (msg.getId().length() == 0) {
                    messagesList.remove(msg);
                }
        }
    }

有时会抛出“并发修改异常”,我尝试将该方法声明为“同步”,但它仍然没有帮助,并且我无法声明块同步,因为它是静态方法并且没有“this”引用.

如果我需要启动另一个异步任务,我也尝试停止正在运行的异步任务,但它也没有帮助。

帮助表示赞赏。

4

6 回答 6

5

这与同步无关。您正在使用迭代器来循环messagesList,然后remove在迭代期间使用它来修改它。您不能这样做,因为ArrayList如果在迭代期间修改列表,则迭代器会失败。从文档

此类的iteratorlistIterator方法返回的迭代器是快速失败的:如果在创建迭代器后的任何时候列表在结构上被修改,除了通过迭代器自己的removeadd方法之外的任何方式,迭代器将抛出一个ConcurrentModificationException.

您的增强for循环只是使用 an 的语法糖Iterator,因此您可以明确说明,然后使用迭代器的remove方法

Iterator<Message> it = messagesList.iterator();
while (it.hasNext()) {
    if (it.next().getId().length == 0) {
       it.remove();
    }
}

或者,您可以只使用一个简单的for循环向后运行并索引到ArrayList(因为get(int)是对 an 的廉价且恒定时间的操作ArrayList,并非所有Lists 都如此):

int index;
for (index = messagesList.length - 1; index >= 0; --index) {
    if (messagesList.get(index).getId().length == 0) {
       messagesList.remove(index);
    }
}
于 2012-10-30T11:10:53.163 回答
3

ArrayList返回的迭代器本质上是fail-fast

这个类的迭代器和listIterator方法返回的迭代器是fail-fast:如果在迭代器创建后的任何时候列表在结构上被修改,除了通过迭代器自己的 remove 或 add 方法之外,迭代器将抛出一个ConcurrentModificationException. 因此,面对并发修改,迭代器快速而干净地失败,而不是在未来不确定的时间冒任意的、非确定性的行为。

iterator.remove();您可以基于迭代器显式而不是隐式调用和更改循环。

ArrayList<Message> messagesList = new ArrayList<Message>();
    if (!clearList) {
        messagesList.addAll(messages.getMessagesList());
        for (ListIterator<Message> iterator = messagesList.listIterator();iterator.hasNext();) {
            Message message = iterator.next();
            if (message.getId().length() == 0) {
                iterator.remove();
            }
        }
    }

参考:

  1. For-Each 循环
  2. 数组列表 Java 文档
于 2012-10-30T11:12:50.330 回答
3
 for (Message msg : messagesList) {
                if (msg.getId().length() == 0) {
                    messagesList.remove(msg);
                }
        }

在这段代码中,您messagesList一次使用的代码也将从中删除数据,messagesList这就是您面临错误并发修改异常的原因..

这是解决您问题的更好方法。复制一个数组列表中的所有数据,以便从主列表中删除和删除所有数据。

Message removeMsg = new ArrayList<Message>();
 for (Message msg : messagesList) {
                    if (msg.getId().length() == 0) {
                        removeMsg.add(msg);
                    }
            }

messagesList.removeAll(removeMsg);
于 2012-10-30T11:14:34.763 回答
2

for循环可能会修改它正在迭代的列表。这就是异常的原因。修改是基于条件的这一事实是它不会一直发生的原因,因为不一定要修改列表。

使用 anIterator是一种可能的解决方案,它提供了一种remove()方法。

于 2012-10-30T11:10:51.613 回答
0

您应该Synchronize为此类使用关键字,因为静态方法不属于任何实例

于 2012-10-30T11:14:15.007 回答
0

-您的问题与同步无关,但您面临的 ConcurrentModification 问题用于保护集合不接收错误类型的对象

例如:

防止 Cat 对象进入 Dog 类型的 Collection。

-你可以通过使用来解决这个问题Iterator

ArrayList<Message> messagesList = new ArrayList<Message>();

Iterator<Message> itr = messagesList.iterator();

while(itr.hasNext()){

 Message m = itr.next();

 itr.remove();   // Its remove() method of Iterator NOT ArrayList's

}
于 2012-10-30T11:19:39.170 回答