gpt4 book ai didi

java - 从 Guava RemovalListener 重新插入条目是否安全?

转载 作者:搜寻专家 更新时间:2023-10-30 20:53:55 29 4
gpt4 key购买 nike

我有一个 Guava Cache(或者更确切地说,我正在从 MapMaker 迁移到 Cache)并且值代表长期运行工作。我想将 expireAfterAccess 行为添加到缓存中,因为这是清理缓存的最佳方式;但是,即使一段时间内未通过缓存访问该作业,它可能仍在运行,在这种情况下,我需要防止它从缓存中删除。我有三个问题:

  1. 重新插入在 RemovalListener 回调期间移除的缓存条目是否安全?

  2. 如果是这样,它是否是线程安全的,这样 CacheLoader 不可能在 RemovalListener 回调仍在发生时为该键生成第二个值在另一个线程中?

  3. 有没有更好的方法来实现我想要的?这不是严格/只是一个“缓存”——每个键只使用一个值是至关重要的——但我也想在它代表的作业完成后将条目缓存一段时间。我之前使用过 MapMaker,我需要的行为现在在该类中已弃用。在作业运行时定期 ping map 是不雅的,在我的情况下,不可行。或许正确的解决方案是拥有两张 map ,一张没有驱逐,另一张有,并在它们完成时迁移它们。

我也会提出一个功能请求 - 这将解决问题:允许锁定单个条目以防止逐出(然后随后解锁)。

[编辑以添加一些细节]:此 map 中的键指的是数据文件。这些值可以是正在运行的写入作业、已完成的写入作业,或者 - 如果没有作业正在运行 - 一个只读的、在查找时生成的对象,其中包含从文件中读取的信息。每个文件只有零个或一个条目,这一点很重要。我可以为这两件事使用单独的映射,但必须在每个键的基础上进行协调,以确保一次只存在一个或另一个。就获得正确的并发性而言,使用单个映射使其更简单。

最佳答案

我不完全清楚确切的问题,但另一种解决方案是使用 softValues() 而不是最大大小或到期时间的缓存。每次访问缓存值(在您的示例中,开始计算)时,您应该在其他地方维护状态,并对该值进行强引用。这将防止该值被 GC 处理。每当此值的使用降为零(在您的示例中,计算结束并且该值消失是可以的)时,您可以删除所有强引用。例如,您可以使用 AtomicLongMap将缓存值作为 AtomicLongMap 键,并定期在 map 上调用 removeAllZeros()

请注意,正如 Javadoc 所述,使用 softValues() 确实需要权衡取舍。

关于java - 从 Guava RemovalListener 重新插入条目是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8764405/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com