我們正在執行銀行應用程序的負載測試/基準測試。當與大約100個虛擬用戶一起運行時,我們得到ConcurrentModificationException
作爲錯誤之一。下面是堆棧跟蹤:從LinkedHashSet創建ArrayList時防止發生ConcurrentModificationException
java.util.ConcurrentModificationException
at java.util.LinkedHashMap$LinkedHashIterator.nextEntry(LinkedHashMap.java:373)
at java.util.LinkedHashMap$KeyIterator.next(LinkedHashMap.java:384)
at java.util.AbstractCollection.toArray(AbstractCollection.java:124)
at java.util.ArrayList.<init>(ArrayList.java:131)
at my.package.AuthorizationHelper.getAuthModuleList
下面在getAuthModuleList()
這是造成異常的部分:
private static final LinkedHashSet MODULE_SET = new LinkedHashSet();
public static List getAuthModuleList(..)
{
MODULE_SET.clear();
....
MODULE_SET.add(getAllrequiredModules());
List userLevelModules = getAllUserLevelModules();
if (userLevelModules != null) {
MODULE_SET.addAll(userLevelModules);
}
userLevelModules = new ArrayList(MODULE_SET); //Exception here
return userLevelModules;
}
模塊需要,以便與所需的那些第一因此使用LinkedHashSet
執行。
以下是我的事業,爲CME的理解:
- 交易用戶A調用此方法。
- 與此同時,用戶B也稱這種方法。
- 當用戶A到達異常行時,用戶B的併發訪問已經發生變異
MODULE_SET
。 - 由於上述原因,ArrayList的實現拋出異常。
如何代碼應該進行修改,以防止上述不破壞功能按我的理解:
改變這一行:
userLevelModules = new ArrayList(MODULE_SET);
爲了這個片斷:
LinkedHashSet moduleSetCopy = new LinkedHashSet(MODULE_SET);
// userLevelModules = new ArrayList(MODULE_SET);
userLevelModules = new ArrayList(moduleSetCopy);
所以我的問題是,
- 我的分析是否正確?
- 我應該使同步副本使用其中一個集合方法或是正常的副本足夠?
注意,應用程序使用甲骨文JRockit的(R)(建R28.2.5-20-152429-1.6.0_37-20120927-1915窗口-x86_64的,編譯模式),而不是標準的Sun JDK。我們需要模擬生產水平的環境,因此不使用後者。
UPDATE:不確定是否與回答相關,但MODULE_SET
在方法開始時被清除。
您可以從任何MODULE_SET的修改過的獲得'ConcurrentModificationException'。基本上你需要同步整個方法。, – kiheru