我有一个静态方法,我从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);
}
}
}
有时会抛出&#39;并发修改例外&#39;,我已经尝试将该方法声明为&#39; synchronized&#39;但它仍然没有帮助,我不能声明块同步,因为它是一个静态的方法,没有&#39;这个&#39;参考
如果我需要启动另一个,我也尝试停止运行asynctask,但它也没有帮助。
帮助表示赞赏。
答案 0 :(得分:5)
这与同步无关。您正在使用迭代器循环遍历messagesList
,但在迭代期间使用remove
来修改它。您不能这样做,因为ArrayList
的迭代器在迭代期间修改列表时会失败。来自the docs:
此类的
iterator
和listIterator
方法返回的迭代器是 fail-fast :如果在创建迭代器后的任何时候对列表进行结构修改,则任何除了通过迭代器自己的remove
或add
方法之外,迭代器将抛出ConcurrentModificationException
。
你的enhanced for
loop只是使用Iterator
的语法糖,所以你可以将它显式化,然后使用迭代器的remove
method:
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);
}
}
答案 1 :(得分:3)
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();
}
}
}
参考文献:
答案 2 :(得分:3)
for (Message msg : messagesList) {
if (msg.getId().length() == 0) {
messagesList.remove(msg);
}
}
在此代码中,您同时使用messagesList
来删除messagesList
中的数据,这就是您遇到错误的原因并发修改例外 ..
这是解决问题的更好方法。将所有数据复制到一个arraylist中以删除&amp;从主列表中删除所有数据。
Message removeMsg = new ArrayList<Message>();
for (Message msg : messagesList) {
if (msg.getId().length() == 0) {
removeMsg.add(msg);
}
}
messagesList.removeAll(removeMsg);
答案 3 :(得分:2)
for
循环可能会修改迭代的列表。这是异常的原因。修改基于条件的事实是它不会一直发生的原因,因为列表不一定被修改。
使用Iterator
是一种可行的解决方案,它提供了remove()
方法。
答案 4 :(得分:0)
您应该为此类使用Synchronize
关键字,因为静态方法不属于任何实例
答案 5 :(得分:0)
- 您的问题不与同步相关联,但您遇到的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
}