尽管使用了Iterator和synchronized,但ConcurrentModificationException

时间:2017-12-05 10:00:22

标签: java multithreading iterator listiterator

公共类RetryHandler扩展Thread { private ArrayList< RetryMessage> retryMessages; private Object syncObject = new Object(); private RetryHandler(){     this.setName(" retryhlr&#34); } public Boolean addMessage(IfgExchangeRequestBase msg,int token){     synchronized(syncObject){         retryMessages.add(new RetryMessage(msg,token));         返回true;     } } public Boolean removeMessage(整数标记){     synchronized(syncObject){         retryMessages.removeIf(X-> x.getToken()等于(令牌));         返回true;     } } @覆盖 public void run(){     while(isRunning){         if(!isPaused){             synchronized(syncObject){                 的ListIterator< RetryMessage> tempRTMessages = retryMessages.listIterator();                 而(tempRTMessages.hasNext()){                     RetryMessage rtmsg = tempRTMessages.next();                     if(....)){                         tempRTMessages.remove();                     如果(...)                         尝试{                             int token = fetch()                             rtmsg.retried();                             rtmsg.setToken(令牌);                         } catch(SAGException e){                     }                 }             }         }     } } } 如您所见,RetryHandler扩展了Thread,它迭代内部列表retryMessages。尽管使用了Iterator并且同步我得到了ConcurrentModificationException。 addMessage和removeMessage已在其他线程中使用。 注意:我使用了ListIterator但结果是一样的。和RetryMessage rtmsg = tempRTMessages.next();提出这个例外。 更新:异常引发RetryMessage rtmsg = tempRTMessages.next();

1 个答案:

答案 0 :(得分:0)

由于异常,您遇到错误,因为您正在迭代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
}