在Guava的地图中驱逐的懒惰

时间:2011-05-05 14:28:11

标签: java hashmap guava concurrenthashmap

目前的地图驱逐算法非常懒惰。看起来只有在访问数据结构时才会驱逐过期的对象。

例如,从地址到索引器的映射定义为:

ConcurrentMap<Address, Indexer> indexers = new MapMaker()
  .expireAfterAccess( EXPIRATION, TimeUnit.SECONDS)
  .evictionListener( new IndexEvicted())
  .makeMap();

导致了相当令人惊讶的模式:虽然给定地址的containsKey()返回false,但在该地址的索引器被驱逐之后立即返回。

建议的方法是什么使清理过程更加实时?即删除接近实际到期时间的对象。

更新:我想通过实时更清楚地说明我的意思。对于上面的示例,EXPIRATION为10秒,我希望看到插入的对象在上次访问后10秒内被逐出。现在没有发生 - 必须以某种方式使用地图来开始驱逐。如果地图完全未使用,则该对象可以在那里停留多年。

3 个答案:

答案 0 :(得分:4)

为了及时驱逐,Guava需要实现某种后台线程或定时重复任务。这样做会使地图变得更加沉重,并且更难以在J2EE或环境中使用,在这些环境中,安全策略会阻止线程无法生成。

如果您关心及时驱逐,请设置您自己的触摸地图的定时线程。

另一方面,我同意让垃圾收集器触发驱逐会很好......例如使用SoftReference和终结器。 (是的,我知道终结者大多是邪恶的,我只是建议一个可选的最后策略。)

答案 1 :(得分:2)

除了expireAfterWrite之外,还有一个expireAfterAccess方法。这可能符合法案。

来自javadoc

  

指定自条目创建或替换后经过固定的持续时间后,应自动从地图中删除每个条目。请注意,更改条目的值将重置其到期时间。

注意:expireAfterAccessexpireAfterWrite都是“实时”,只是一个根据上次写入时间到期,另一个是基于上次访问时间。

答案 2 :(得分:1)

虽然Dilum的答案最有意义,但同时请注意,触摸自动驱逐的数据结构必然会驱逐所有过期的条目。大多数到期发生在相对较小的批次中,因此,如果您有大量的同时到期,您可能需要多次触摸数据结构。不幸的是,我认为没有一种简单的编程方式可靠地完成这项工作。