2015-10-06 34 views
3

Java 8將默認方法的負載添加到集合框架中的接口上;然而,Collections.synchronizedX方法的JavaDoc幾乎沒有改變。我不清楚在他們返回的結果上調用新的默認方法是否安全?對Collections.synchronizedX的結果調用Java 8 Collection默認方法是否安全?

我檢查了Oracle JDK源代碼,它們似乎被覆蓋爲線程安全的,但對於所有的JDK是否有保證?

+4

他們沒有改變javadoc,它保證所有的方法都是線程安全的,通過同步。如果他們沒有將該行爲傳播到默認方法,那就是一個錯誤。 – assylias

+0

@assylias但是,如果您從第三方預JDK 8庫的角度看到此情況,那麼JacaDoc中沒有更改,但其所有收集包裝都不再是線程安全的。但是,我想這也意味着這個問題不能在JDK的範圍之外現實地回答。 –

+1

@ billc.cn:這就是爲什麼你不應該爲這類任務使用第三方庫。但是,這樣的類的線程安全性不會因'默認'方法而改變。它仍然像以前一樣安全,只是複合操作需要額外的努力,這也像以前一樣。 – Holger

回答

3

在OpenJDK的/ OracleJDK的事物的真實狀態如下:

  • spliterator()stream()parallelStream()方法不同步,並且必須從外部手動同步的(類似於iterator()listIterator()之前就存在) 。

  • 其他新方法是同步的,包括forEachremoveIfreplaceAllsortgetOrDefaultputIfAbsentreplacecomputeIfAbsentcomputeIfPresentcomputemerge

這種行爲實際上specified是:

當務之急是用戶通過IteratorSpliteratorStream

穿越,所以你可以期待當上了返回的集合手動同步除了這些明確提到的異常之外的其他方法都是同步的。微妙的問題是,它僅指定爲synchronizedCollection,但不適用於其他方法,並未明確指定,例如,synchronizedListsynchronizedCollection(儘管實際上確實如此)繼承了某些行爲。

請注意,批量處理方法(如forEachreplaceAll)會在整個迭代過程中持有監視器,因此您最終有機會安全地迭代/更新整個集合。但是,您應該瞭解可能的死鎖/飢餓,因爲收集可能會長時間被鎖定。

另請注意,當前狀態引入了syncCollection.forEach(...)syncCollection.stream().forEach(...)之間的差異:第二個呼叫未同步。

UPDATE:我reported在OpenJDK開發商synchronizedXXX方法該規範必須被更新並submitted a patch其接受JDK-9。

+1

是的,甚至更好,因爲'Collections.sort'委託給'List.sort',將它應用到'synchronizedList',您可以獲得線程安全性*和*在原始列表範圍內潛在的高性能執行。當後備列表是一個'ArrayList' ... – Holger