java.util.ConcurrentModificationException
對于這個異常記憶太深刻了,因為面試被問到過!!!而且沒準備,答得一塌糊涂~~
今天,在項目上遇到了這個問題,查日志看到拋出異常的地方是在一個遍歷查詢的方法,沒有增刪改的操作,于是只能往上翻代碼
整理一個整個鏈路,大概流程是:
// 以下為偽代碼
// 方法入口
public void submit(SaveData data){
List list = saveToDB(data);
this.sendToMq(list);
}
// 保存數據,然后推給下游系統
public List saveToDB(SaveData data){
List list = new ArrayList();
// ignore
this.syncSendToRemote(list)
return list;
}
// 推MQ
public void sendToMq(List list){
for(Item item : list){ // throws ConcurrentModificationException
// read and send
}
}
// 推給下游系統
public void syncSendToRemote(List list){
executor.execute(()-> {
list.removeIf(item -> item.name == null);
// send
});
}
拋出異常的地方,在sendToMq()
的遍歷方法,看看list哪里會用到:
- 首先,list是在
saveToDB
中創建 - list會傳給
syncSendToRemote
- 最后才把list傳給
sendToMq()
這就很明顯了,syncSendToRemote
是個異步方法,也就是說,syncSendToRemote
和 sendToMq
有可能在同時執行,就相當于一個典型的并發問題了,兩個線程同時操作list(大概又是前段時間為了優化接口改出來的問題~)
接下來,就是面試題中的“你有遇到過ConcurrentModificationException嗎?如何解決?”的問題了。。(晚點更新)