简体   繁体   English

Guava 地图中驱逐的懒惰

[英]Laziness of eviction in Guava's maps

Current eviction algorithm for maps is quite lazy.当前的地图驱逐算法非常懒惰。 It looks like expired objects are evicted only when the data structure is accessed.看起来过期的对象只有在访问数据结构时才会被驱逐。

For example, the map from addresses to indexers defined as:例如,从地址到索引器的 map 定义为:

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

leads to quite surprising pattern: while containsKey() for the given address returns false, immediately after that indexer for that address is evicted.导致非常令人惊讶的模式:虽然给定地址的containsKey()返回 false,但在该地址的索引器被驱逐后立即返回。

What would be the recommended approach to make the clean up process more real-time?使清理过程更加实时的推荐方法是什么? Ie to remove the objects close to the actual expiration time.即删除接近实际到期时间的对象。

Update: I'd like to more clarify what I mean by real-time.更新:我想更清楚地说明我所说的实时是什么意思。 For the example above, EXPIRATION being 10 seconds, I'd like to see the inserted object evicted in 10 seconds after last access.对于上面的示例,EXPIRATION 为 10 秒,我希望看到插入的 object 在上次访问后 10 秒内被驱逐。 That is not happening now - the map must be used somehow to start the eviction.现在没有发生这种情况 - 必须以某种方式使用 map 来启动驱逐。 If the map is completely unused, the object can stay there for years.如果 map 完全未使用,则 object 可以在那里停留数年。

In order to have timely eviction, Guava would need to implement some sort of background thread or a timed recurring task.为了及时驱逐,Guava 需要实现某种后台线程或定时重复任务。 Doing so would make the map more heavy weight and harder to use in environments like J2EE or environments where the security policy prevents threads from being spawned willy-nilly.这样做会使 map 更重,更难在 J2EE 等环境或安全策略阻止线程随意生成的环境中使用。

If you care about timely eviction, set up your own timed thread that touches the map.如果您关心及时驱逐,请设置您自己的定时线程来接触 map。

On the flip side, I do agree that having a garbage-collector triggered eviction would be nice... for example by using a SoftReference and a finalizer.另一方面,我同意让垃圾收集器触发驱逐会很好......例如通过使用 SoftReference 和终结器。 (Yes, I know finalizers are mostly evil, I am simply suggesting an optional last-resort strategy.) (是的,我知道终结者大多是邪恶的,我只是建议一个可选的最后手段策略。)

There is an expireAfterWrite method in addition to expireAfterAccess .除了expireAfterAccess之外,还有一个expireAfterWrite方法。 That probably fits the bill.这可能符合要求。

From javadoc :javadoc

Specifies that each entry should be automatically removed from the map once a fixed duration has passed since the entry's creation or replacement.指定自创建或替换条目后经过固定持续时间后,应自动从 map 中删除每个条目。 Note that changing the value of an entry will reset its expiration time.请注意,更改条目的值将重置其过期时间。

Note: both expireAfterAccess and expireAfterWrite are "real-time", it's just that one expires elements based on their last write time, the other is based on their last access time.注意: expireAfterAccessexpireAfterWrite都是“实时的”,只是一个根据上次写入时间过期元素,另一个根据上次访问时间过期。

While Dilum's answer makes the most sense, also note that touching a data structure with automatic eviction will not necessarily evict all expired entries.虽然 Dilum 的回答是最有意义的,但还要注意,使用自动驱逐的数据结构不一定会驱逐所有过期的条目。 Most expiry happens in relatively small batches and therefore, if you have a large number of simultaneous expirations, you might have to touch the data structure a number of times.大多数到期发生在相对较小的批次中,因此,如果您有大量同时到期,您可能必须多次接触数据结构。 Unfortunately, I don't think there there is an easy programmatic way to do this reliably.不幸的是,我认为没有一种简单的编程方式可以可靠地做到这一点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM