当前位置: 首页 > 知识库问答 >
问题:

ConcurrentModificationException尽管使用了迭代器和同步

拓拔谭三
2023-03-14
public class RetryHandler extends Thread {

private ArrayList<RetryMessage> retryMessages;
private Object syncObject = new Object();

private RetryHandler() {
    this.setName("retryhlr");
}
public Boolean addMessage(IfgExchangeRequestBase msg, int token) {
    synchronized(syncObject) {
        retryMessages.add(new RetryMessage(msg, token));
        return true;
    }
}

public Boolean removeMessage(Integer token) {
    synchronized(syncObject) {
        retryMessages.removeIf(x->x.getToken().equals(token));  
        return true;
    }
}

@Override
public void run() {
    while(isRunning) {
        if (!isPaused) {
            synchronized(syncObject) {
                ListIterator<RetryMessage> tempRTMessages = retryMessages.listIterator();
                while(tempRTMessages.hasNext()){
                    RetryMessage rtmsg =tempRTMessages.next(); 
                    if(....)) {
                        tempRTMessages.remove();
                    } else if(...)
                        try {
                            int token = fetch()
                            rtmsg.retried();
                            rtmsg.setToken(token);
                        } catch (SAGException e) {
                    }
                }
            }
        }
    }
}

}

正如您所看到的,RetryHandler扩展了线程,该线程在内部列表retryMessages上迭代。尽管使用了Iteratorsynchronized,我还是得到了ConcurrentModificationExceptionaddMessageremoveMessage已在其他线程中使用。

更新:在RetryMessage rtmsg=tempRTMessages上引发异常。next()


共有1个答案

宗政欣可
2023-03-14

由于正在迭代ArrayList,并且在迭代ArrayList时,正在从中删除对象,因此会因异常而遇到错误。对于这种类型的收集,这是一种快速失败的机制。

如果你真的需要从ArrayList中删除项目,你可以做的是创建一个CopyOnWriteArrayList对象,这个对象就是你想要的对象。请参见下面的代码

CopyOnWriteArrayList<RetryMessage> retryMessageCopyOnWrite= new CopyOnWriteArrayList<RetryMessage>(retryMessages);
    Iterator<RetryMessage> retryMessageIterator = retryMessageCopyOnWrite.iterator();
...
<some object modifications here for retryMessageCopyOnWrite>

然后只需将CopyOnWriteArrayList的内容复制到retryMessages列表对象,并将其复制回原始arrayList。

retryMessages = new ArrayList<RetryMessage>(retryMessageCopyOnWrite);

因为您也在使用迭代器本身删除一个项。请阅读此链接:CopyOnWriteArrayList

我建议使用CopyOnWriteArrayList对象来修改列表,而不是使用迭代器本身。

您可以在迭代中使用类似的内容:

RetryMessage temp = iterator.next();
if(do some checking) {
    retryMessageCopyOnWrite.remove(temp); //this removes the current element
}
 类似资料:
  • 我有一个由多个线程操作的ArrayList,由于ArrayList没有同步,所以无法工作。按照教授的指示,我把列表换成了向量。向量是同步的,但我抛出了与同步相关的异常。 为什么会发生这种情况,我如何避免代码中的并发异常?我不想只是玩玩,直到有东西起作用,我想做最好的事情。谢谢! 例外情况: 代码:

  • 所有订阅操作都使用以下内容: 所有取消订阅操作都使用以下内容: 和通知者:

  • 问题内容: 如果我创建两个列表并将其压缩 然后我将z输入到两个列表中 那么,l1的内容就很好了[(1,7),(2,8),(3,9)],但是l2的内容只是[]。 我猜想这是python关于可迭代项的一般行为。但是,作为从C家族迁移的新手程序员,这对我来说没有意义。为什么会这样表现?有办法解决这个问题吗? 我的意思是,是的,在这个特定示例中,我可以将l1复制到l2中,但是总的来说,在迭代一次之后,是否

  • 问题内容: 我从下面的代码中获得,我可以找到原因。我可以成功地从csv文件读取数据,并创建一个名为课程列表的arraylist。那么我需要将其排序到一个数组列表,该数组的每个单元格都包含相同课程(名称相似的课程)的数组列表。但是当我运行它时会生成ConcurrentModificationException,我不明白为什么… 这是我的CourefileSorterclass: 问题答案: 将它们分

  • 问题内容: 我下面有以下代码 现在我正在使用一个Android游戏,并且上面的代码以多线程方式运行。现在我有一个例外。我已经研究了如何解决问题,但似乎对我没有帮助。我在上面的代码上所做的是 随机删除一个条目 。我如何在那里实现它? 问题答案: 除非使用,否则不能在迭代时从集合中删除元素。 这就是导致异常的原因。 使用Iterator#remove()在遍历集合时删除元素,例如 编辑 :(响应OP的

  • 即使使用迭代器,删除列表中的第1和第2个元素也会出现问题。 我已经阅读了以下的线索,但无法解决我的问题(这些是最相关的,但我也检查了其他材料): 尝试从列表中移除元素时的ConcurrentModificationException