Guava 地图中的驱逐惰性

发布于 2024-11-05 10:09:13 字数 529 浏览 1 评论 0原文

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

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

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

导致非常令人惊讶的模式:在该地址的索引器被逐出后,给定地址的 containsKey() 立即返回 false。

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

更新:我想进一步澄清实时的含义。对于上面的示例,EXPIRATION 为 10 秒,我希望看到插入的对象在上次访问后 10 秒内被逐出。现在这种情况还没有发生——必须以某种方式使用地图来开始驱逐。如果地图完全未使用,该物体可能会在那里停留数年。

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:

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.

What would be the recommended approach to make the clean up process more real-time? I.e. 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. That is not happening now - the map must be used somehow to start the eviction. If the map is completely unused, the object can stay there for years.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

じ违心 2024-11-12 10:09:13

为了及时驱逐,Guava 需要实现某种后台线程或定时重复任务。这样做会使映射变得更重,并且更难以在 J2EE 等环境或安全策略阻止随意生成线程的环境中使用。

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

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

In order to have timely eviction, Guava would need to implement some sort of background thread or a timed recurring task. 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.

If you care about timely eviction, set up your own timed thread that touches the 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. (Yes, I know finalizers are mostly evil, I am simply suggesting an optional last-resort strategy.)

草莓味的萝莉 2024-11-12 10:09:13

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

来自 javadoc

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

注意:expireAfterAccessexpireAfterWrite 都是“实时”的,只是一个根据上次写入时间使元素过期,另一个根据上次访问时间使元素过期。

There is an expireAfterWrite method in addition to expireAfterAccess. That probably fits the bill.

From 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. 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.

赏烟花じ飞满天 2024-11-12 10:09:13

虽然 Dilum 的答案最有意义,但还要注意,通过自动逐出来接触数据结构不一定会逐出所有过期的条目。大多数到期发生在相对较小的批次中,因此,如果您有大量同时到期的情况,您可能必须多次接触数据结构。不幸的是,我认为没有一种简单的编程方法可以可靠地做到这一点。

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. 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文