2012-05-04 66 views
7

在番石榴圖書館,我很困惑爲什麼Cache.asMap()不符合Cache.size(),除非Cache.cleanUp()被調用。爲什麼Cache.asMap()與Cache.size()不一致?

Cache<Object, Object> cache = CacheBuilder.newBuilder() 
      .expireAfterWrite(1, TimeUnit.SECONDS) 
      .build(); 
cache.get(...); 
... 
//After some seconds, all entries are expired. 
//cache.asMap() is EMPTY Map, but cache.size() != 0 

所以我的問題:是不是錯誤,Cache.asMap()不是Cache.size()一致? 雖然我注意到的Cache.size()的Javadoc:

/** 
    * Returns the **approximate** number of entries in this cache. 
    */ 

我只能猜測它涉及到併發環境。 Cache.cleanUp()究竟做了什麼?

回答

13

番石榴的緩存設計圍繞鎖定攤銷,並且cleanUp方法強制緩存達到一致狀態。 Map.size()方法是一種近似方法,但可以計算因到期或參考驅逐而正在等待移除的條目。在Guava的緩存中近似值的可見性對於應用程序來說很少有興趣,它往往會將緩存視爲臨時數據存儲。 Map對緩存的不同期望導致了asMap方法允許將緩存視爲地圖,但不利於開發人員以這種方式感知。

高速緩存的實現細節在StrangleLoop 2011會議slides中涵蓋。的design document,Guava的緩存來源於此,也可能是有趣的,但描述了一種稍微不同的方法。

9

本給出了很好的高層回覆。低級響應是:

asMap()asMap()視圖具有遍歷高速緩存中的每個元素的優點,因此可以跳過正在等待清理的無效項。另一方面,size()預計是一個快速操作,並且遍歷整個緩存僅僅是爲了獲得更準確的大小估計是愚蠢的。

CacheBuilder javadocs詳細介紹了在各種情況下需要進行的清理(例如expireAfterWrite,在您的情況下)。

+1

謝謝,查爾斯!我大致瀏覽了源代碼,'size()'只是對段的數量進行總結,正如您所提到的那樣 - 「遍歷整個緩存只是爲了獲得更準確的大小估計」:)高度複雜的設計! –

相關問題