2009-10-29 38 views
5

LRU LinkedHashMap的限制大小我想創建LinkedHashMap中,將根據可用內存限制其大小(即當freeMemory + (maxMemory - allocatedMemory)低於一定閾值)。這將用作緩存的一種形式,可能使用「最近最少使用」作爲緩存策略。根據可用內存

我擔心的是,雖然allocatedMemory還包括(I假設)未垃圾收集的數據,並且因此將過度估計所使用的存儲器的量。我擔心這可能會產生意想不到的後果。

例如,LinkedHashMap的可能會保持刪除項目,因爲它認爲沒有足夠的可用內存,但可用內存也不會增加,因爲這些刪除的項目不會被垃圾立即收集。

有沒有人有這種類型的事情的經驗?我的擔憂是否值得?如果是這樣,任何人都可以提出一個好方法?

我要補充一點,我也希望能夠「鎖定」的高速緩存,基本上說:「好了,從現在開始,不要刪除,因爲內存使用問題什麼」。

+0

你在這裏有什麼應用?如果不知道背景的意圖是什麼,很難想出一個好的答案。你的HashMap是緩存還是什麼? – jprete 2009-10-29 20:17:50

+0

jprete,我試圖澄清這一點 - 你是對的,它的緩存 – sanity 2009-10-29 20:24:02

+0

這是一個典型的例子,其中GC和java內存管理顯示了它真正的混亂面貌。在C++中這麼做會很簡單*。使用GC,你不能執行像刪除或免費的命令。 – 2009-10-29 20:57:21

回答

1

我知道我有偏見,但我真的要強烈建議我們這個MapMaker。使用softKeys()或softValues()功能,具體取決於它是關鍵的GC集合還是更適合描述條目何時清理的值的值。

+1

我想使用MapMaker(我廣泛使用Google Collections在我的代碼中),但是有什麼辦法可以使它像一個LRU緩存一樣根據可用內存進行擴展?另外,有沒有什麼辦法可以「鎖定」它,以便它不會再刪除條目來回應垃圾回收? – sanity 2009-11-05 14:14:13

+1

「表現得像一個LRU緩存......」 - 這幾乎完全描述了軟引用會給你什麼,是的。 「鎖定」它 - 唯一明智的答案涉及複製地圖:地圖<密鑰,Val > strongCache = Maps.newHashMap(cache); – 2009-11-05 17:45:59

+0

抱歉關於<垃圾;沒有預覽,所以我不得不猜測我是否必須逃脫。 :( – 2009-11-05 17:46:37

0

緩存往往是有問題的。 IIRC,Sun的JRE中有一個SoftCache,它有許多問題。

無論如何,最簡單的做法是在地圖上用SoftReference秒。只要SoftReference加上Map.Entry的開銷顯着低於緩存數據,這應該可以正常工作。

或者,您可以像WeakHashMap那樣使用ReferenceQueue並輪詢它或對其進行輪詢(不幸的是,每個實例有一個線程)。請注意同步問題。

「鎖定」地圖,你可能想避免,如果有必要。你需要對所有數據保持強有力的引用(如果不爲空,則會逐出)。這將是醜陋的。

+0

對於鎖定,我想我可以簡單地將整個東西複製到一個普通的HashMap – sanity 2009-10-29 20:47:21

+0

那麼,你可以複製地圖的內容,但是你也必須解引用軟引用。雖然複製而不是鎖定是一個更好的方法。 – 2009-10-29 21:43:08

0

我強烈建議使用類似Ehcache的東西,而不是重新發明緩存系統。它使用起來非常簡單,非常易於配置,並且效果很好。

0

就像馬特b說的那樣,Ehcache或者JbossCache就是一個不錯的第一步。

如果您想要輕量級和正在處理的東西,請查看Google收藏集。例如,您可以使用MapMaker(http://google-collections.googlecode.com/svn/trunk/javadoc/index.html?com/google/common/collect/BiMap.html)製作具有軟/弱鍵和值的地圖,因此它只會緩存那些有空間的項目(儘管您不會獲得LRU)。

+0

糟糕 - 更好的鏈接:http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/MapMaker.html – nojo 2009-10-30 14:51:42

0

我在過去同樣的需要,這是我如何實現我的緩存:

  • 存在緩存內存管理器,它有一個最小和最大的內存限制(最大限制它的事項反正)
  • 每個註冊緩存具有以下(重要的)參數:最大容量(你最有上限的時候,你不想去持有超過X項目的更多)&%的內存使用率
  • 我用LinkedHashMap中和一個ReentrantReadWriteLock來保護緩存。
  • 每隔X放置我計算每個條目的平均內存消耗,並在計算的內存限制>允許的內存限制時觸發逐出(異步)。
  • 當然內存計算實際上並不顯示實際的內存消耗,但將計算的內存與實際值進行比較(使用分析器),我發現它足夠接近。

我計劃也把一個額外的保護上的緩存,驅逐的情況下,看跌期權將會比基於內存驅逐快,但到現在爲止我沒有找到需要做到這一點。