7

在 Guava Library 中,我很困惑为什么Cache.asMap()不符合Cache.size(),除非Cache.cleanUp()被调用。

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()?虽然我注意到的 javadocCache.size()是:

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

我只能猜测它与并发环境有关。究竟是Cache.cleanUp()做什么的?

4

2 回答 2

15

Guava 的缓存是围绕锁摊销设计的,该cleanUp方法强制缓存达到一致的状态。该Map.size()方法是一个近似值,但可能会计算由于过期或引用驱逐而等待删除的条目。Guava 缓存中近似值的可见性很少对应用程序感兴趣,它倾向于将缓存视为临时数据存储。Map 对缓存的不同期望导致asMap允许将缓存视为地图的方法,但不喜欢开发人员以这种方式感知它。

缓存的实现细节在 StrangleLoop 2011 会议幻灯片中有所介绍。Guava的缓存源自的设计文档可能也很有趣,但描述了一种略有不同的方法。ConcurrentLinkedHashMap

于 2012-05-04T05:22:29.623 回答
12

本给出了很好的高层回应。低级响应是:

asMap()视图可以遍历缓存中的每个元素,因此可以跳过等待清理的无效条目。另一方面,size()预计这将是一个快速的操作,而为了获得更准确的大小估计而遍历整个缓存是很愚蠢的。

CacheBuilderjavadocs 更详细地介绍了在各种情况下需要进行的清理(例如,expireAfterWrite在您的情况下)。

于 2012-05-04T12:41:13.117 回答