日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

避免在ConcurrentHashMap.computeIfAbsent()中进行递归

發布時間:2023/12/3 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 避免在ConcurrentHashMap.computeIfAbsent()中进行递归 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

有時我們會提供糟糕的建議。 就像該文章中有關如何將Java 8用于緩存的功能性方法來計算斐波那契數的文章一樣 。 正如我們的讀者之一馬蒂亞斯(Matthias)在評論中注意到的那樣 ,提出的算法可能永遠不會停止。 考慮以下程序:

public class Test {static Map<Integer, Integer> cache = new ConcurrentHashMap<>();public static void main(String[] args) {System.out.println("f(" + 25 + ") = " + fibonacci(25));}static int fibonacci(int i) {if (i == 0)return i;if (i == 1)return 1;return cache.computeIfAbsent(i, (key) -> {System.out.println("Slow calculation of " + key);return fibonacci(i - 2) + fibonacci(i - 1);});} }

它將至少在以下Java版本上無限期運行:

C:\Users\Lukas>java -version java version "1.8.0_40-ea" Java(TM) SE Runtime Environment (build 1.8.0_40-ea-b23) Java HotSpot(TM) 64-Bit Server VM (build 25.40-b25, mixed mode)

這當然是“功能” 。 ConcurrentHashMap.computeIfAbsent() Javadoc讀取:

如果指定的鍵尚未與某個值關聯,則嘗試使用給定的映射函數計算其值,除非為null,否則將其輸入此映射。 整個方法調用是原子執行的,因此每個鍵最多可應用一次該功能。 在進行計算時,可能會阻止其他線程對此映射進行的某些嘗試的更新操作,因此計算應簡短而簡單, 并且不得嘗試更新此映射的任何其他映射

盡管并非出于相同的并發原因,“不得”的措辭是明確的合同,我的算法違反了該合同。

Javadoc還讀取:

拋出:

IllegalStateException-如果計算可檢測到嘗試對此地圖進行遞歸更新,否則將永遠無法完成

但是不會拋出該異常。 也沒有任何ConcurrentModificationException。 相反,該程序永遠不會停止。

解決此具體問題的最簡單的使用現場解決方案是不使用ConcurrentHashMap,而僅使用HashMap:

static Map<Integer, Integer> cache = new HashMap<>();

覆蓋超類型合約的子類型

Map.computeIfAbsent() HashMap.computeIfAbsent()或Map.computeIfAbsent() Javadoc禁止這種遞歸計算,這當然是荒謬的,因為緩存的類型是Map<Integer, Integer> ,而不是ConcurrentHashMap<Integer, Integer> 。 子類型徹底重新定義超級類型協定是非常危險的( Set vs. SortedSet是問候)。 因此,在超級類型中也應禁止執行此類遞歸。

進一步參考

盡管合同問題只是人們的看法,但停頓問題顯然是一個漏洞。 我還在Stack Overflow上記錄了此問題,在該問題中 , Ben Manes提供了一個有趣的答案,導致了先前的錯誤報告(截至2015年初尚未解決):

  • https://bugs.openjdk.java.net/browse/JDK-8062841

我自己的報告(可能是上述報告的副本)也很快被接受,原因是:

  • https://bugs.openjdk.java.net/browse/JDK-8074374

Oracle正在研究此問題時,請記住:

切勿在ConcurrentHashMap.computeIfAbsent()方法內部進行遞歸。 如果您正在實現集合,并且認為編寫一個可能無限的循環是個好主意,請再考慮一下,然后閱讀我們的文章:

無限循環。 或者:可能出錯的任何東西都可以 )

墨菲總是對的。

翻譯自: https://www.javacodegeeks.com/2015/03/avoid-recursion-in-concurrenthashmap-computeifabsent.html

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的避免在ConcurrentHashMap.computeIfAbsent()中进行递归的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。