[英]Concurrent modification exception from a static method that being called asynctask
我有一个静态方法,该方法是从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”引用。
如果需要启动另一个异步任务,我也曾尝试停止运行该异步任务,但这也无济于事。
帮助表示赞赏。
这与同步无关。 您正在使用迭代器遍历messagesList
,然后在迭代过程中使用remove
进行修改。 您不能这样做,因为如果在迭代过程中修改了列表,则ArrayList
的迭代器会失败。 从文档 :
此类的
iterator
和listIterator
方法返回的iterator
是快速失败的 :如果在创建迭代器之后的任何时间以任何方式对列表进行结构修改,则除了通过迭代器自己的remove
或add
方法之外,迭代器都会抛出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);
}
}
ArrayList返回的迭代器本质上是fail-fast
。
此类的迭代器和
listIterator
方法返回的迭代器是fail-fas
:如果在创建迭代器后的任何时间以任何方式对列表进行结构修改,则除了通过迭代器自己的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();
}
}
}
参考文献:
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);
for
循环可能会修改要对其进行迭代的列表。 这是导致异常的原因。 修改是基于条件的事实是其并非始终都发生的原因,因为列表不一定需要修改。
使用Iterator
是一种可能的解决方案,它提供了remove()
方法。
您应该为此类使用Synchronize
关键字,因为静态方法不属于任何实例
-您的问题是不与同步有关,但ConcurrentModification你所面临的问题是用来保护收集采取的错误类型的对象。
例如:
防止Cat对象进入Dog类型的集合。
-您可以使用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
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.