2011-03-13 40 views
5

我的代碼拋出如下異常:在JDK6.0或其他庫中是否有任何併發​​LinkedHashSet?

java.util.ConcurrentModificationException 
     at java.util.LinkedList$ListItr.checkForComodification(LinkedList.java:761) 
     at java.util.LinkedList$ListItr.next(LinkedList.java:696) 
     at java.util.AbstractCollection.addAll(AbstractCollection.java:305) 
     at java.util.LinkedHashSet.<init>(LinkedHashSet.java:152) 
     ... 

我想ConcurrentLinkedHashSet修復它,

但我只在java.util.concurrent發現ConcurrentSkipListSet,這是TreeSet,不LinkedHashSet

任何easies方式來獲得在JDK6.0中使用ConcurrentLinkedHashSet

感謝您的幫助:)

+4

你想添加或刪除元素,同時遍歷說相關的哈希集?該解決方案可能不是使用併發集合,而是使用迭代器在中間循環中執行修改 –

+0

我在此處獲得了'ConcurrentLinkedHashSet':http://artemis.ms.mff.cuni.cz/viewvc/pogamut/trunk/project/Core/src/cz/cuni/amis/utils/sets /?pathrev = 2475 :) – Koerr

+1

我並不是說你無法獲得ConcurrentLinkedHashSet,但你的問題可能來自修改你的linkedhashset in一個循環,如果是這樣的話,使用linkedhashset中的迭代器將是一個更合適的解決方案。除非程序中涉及線程,否則不應該需要併發鏈接哈希集合。 –

回答

10

ConcurrentModificationException與您想要的表單中的併發無關。這只是意味着在迭代Collection時,某人(可能是您自己的代碼 - 經常發生這種情況)會改變它,即添加/刪除一些值。

確保您使用Iterator從集合中刪除值,而不是集合本身。

編輯:如果真的有另一個線程同時訪問集合,那麼從標準庫獲得的弱同步無論如何都是毫無用處的,因爲您必須在整個操作過程中阻止集合,而不僅僅是爲一個添加/刪除!即像

synchronize(collection) { 
    // do stuff here 
} 
+0

請注意,這會更改集合的合同以及(取決於使用集合的組件以及如何使用集合),更改它可能會非常棘手(讓所有客戶端都符合要求)。修辭問題:當你迭代由不同的組件/框架提供給你的集合時,你認爲如果實現對於併發迭代是安全的,並且可以並行修改它嗎?機會是其他組件的作者也沒有想到... –

0

不幸的不是。你可以實現你自己的,包裝一個ConcurrentHashMap和一個ConcurrentLinkedQueue,但是這不會允許你輕鬆地刪除值(刪除將是O(N),因爲你必須迭代隊列中的所有內容)...

你是否在使用LinkedHashSet?可能能夠建議替代方案...

4

您始終可以使用Collections.synchronizedMap(myMap);創建同步收集。但是,在迭代過程中嘗試更改地圖(我認爲這是導致錯誤的原因)仍然是個問題。

從文檔的synchronizedMap:

返回由指定映射支持的同步(線程安全的)映射。爲了保證串行訪問,通過返回的映射完成對備份映射的所有訪問是非常重要的。

當務之急是用戶 手動返回 地圖上遍歷它的任何 收集意見時同步......不遵循 這個建議可能導致 非確定性的行爲。

這是因爲

  • 常併發收集確實保證原子GET /把,但迭代過程中不鎖定整個集合,這將是太慢了。迭代中沒有併發保證,實際上這是針對地圖的許多操作。

  • 如果您在迭代過程中發生變化,那麼它並不是真正的併發性,因爲無法確定正確的行爲 - 例如,如何協調迭代器返回hasNext == true並從中刪除(可能是下一個值)採集?

相關問題