同时修改异常,来自称为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);
                }
        }
    }

有时会抛出"并发修改异常",我尝试将该方法声明为"同步",但仍然没有帮助,我无法声明该块同步,因为这是一种静态方法,没有'这个'参考。

如果我需要启动另一个,我也试图停止运行的异步,但这也没有帮助。

帮助赞赏。

这与同步无关。您正在使用迭代器来循环messagesList,然后在迭代期间使用remove对其进行修改。您无法做到这一点,因为当迭代期间修改列表时,ArrayList的迭代器失败。从文档中:

该类的iterator返回的迭代器和listIterator方法是 fafs-fast :如果列表在创建迭代器后的任何时间进行结构修改,则以迭代器自己的removeadd方法,迭代器将抛出ConcurrentModificationException

您增强的for循环只是使用Iterator周围的句法糖,因此您可以显式进行该方法,然后使用迭代器的remove方法:

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

另外,您可以只使用简单的for向后运行并索引到ArrayList(因为get(int)ArrayList上的便宜且恒定的时间操作,这对所有List s并非如此):

int index;
for (index = messagesList.length - 1; index >= 0; --index) {
    if (messagesList.get(index).getId().length == 0) {
       messagesList.remove(index);
    }
}
 for (Message msg : messagesList) {
                if (msg.getId().length() == 0) {
                    messagesList.remove(msg);
                }
        }

在此代码中,您一次使用messagesList您也将从messagesList删除数据,这就是为什么您遇到错误并发修改异常 ..

这里更好地解决了您的问题。将所有数据复制到一个阵列列表中以删除&amp;从主列表中删除所有数据。

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

arraylist返回的迭代器是 fail-fast

该类的迭代器返回的迭代器和listIterator方法是fail-fas t:如果列表在创建迭代器后的任何时间进行了结构修改,除非通过迭代器自己的删除或添加方法,否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. arraylist java docs

for循环可能会修改其迭代的列表。这是例外的原因。修改是基于条件的事实是由于列表不一定修改的原因。

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

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

- 您的问题是不是与同步关联的,但是您所面临的consurrentModification的问题用于保护收集免受收集错误类型的对象。

例如:

防止猫对象进入狗类型的集合。

- 您可以使用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
}

最新更新