gpt4 book ai didi

java - 自*第一次*插入以来,Java中是否有一个过期映射在一段时间后使元素过期?

转载 作者:行者123 更新时间:2023-12-03 18:45:48 25 4
gpt4 key购买 nike

我尝试查看缓存机制,例如 Guava 的 Cache .它们的有效期仅自上次更新以来。

我正在寻找的是一种数据结构,它存储 key 并在第一次插入后经过一段时间后清理 key 。我正计划将该值设为某个计数器。

一个场景可能是一个沉默的 worker ,他第一次做一些工作,但在一段时间内保持沉默 - 即使需要工作。如果在到期时间过后要求工作,他将完成工作。

知道这样的数据结构吗? 谢谢。

最佳答案

为此,有几个选项。

被动移除

如果不需要在过期 key 过期后或按设定的时间间隔清除过期的 key (即 key 过期或在某个设定的时间间隔内不需要删除 key ),则 PassiveExpiringMap来自 Apache Commons Collections 是一个不错的选择。尝试访问此映射中的 key 时,将检查该 key 的生存时间 (TTL)(所有 key 具有相同的 TTL),如果该 key 已过期,则将其从映射中删除并 null被退回。这个数据结构没有主动清理机制,所以过期的条目只有在key对应的TTL过期后才被访问。

缓存

如果需要更多基于缓存的功能(例如最大缓存容量和添加/删除监听),Google Guava 提供了 CacheBuilder类(class)。这个类比 Apache Commons 替代方案更复杂,但它也提供了更多的功能。如果这旨在用于更多基于缓存的应用程序,那么这种权衡可能是值得的。

线程拆卸

如果需要主动删除过期 key ,则可以生成一个单独的线程来负责删除过期 key 。在查看可能的实现结构之前,应该注意这种方法的性能可能低于上述替代方案。除了启动线程的开销外,线程可能会导致与访问 map 的客户端发生争用。例如,如果客户端想要访问一个键并且清理线程当前正在删除过期的键,则客户端将阻塞(如果使用同步)或具有不同的映射 View (包含哪些键值对)在 map 中)如果采用了某种并发机制。

话虽如此,使用这种方法很复杂,因为它需要将 TTL 与 key 一起存储。一种方法是创建一个 ExpiringKey ,例如(每个键可以有自己的 TTL;即使所有键最终都具有相同的 TTL 值,这种技术不需要创建 Map decoratorMap 的其他一些实现界面):

public class ExpiringKey<T> {

private final T key;
private final long expirationTimestamp;

public ExpiringKey(T key, long ttlInMillis) {
this.key = key;
expirationTimestamp = System.currentTimeMillis() + ttlInMillis;
}

public T getKey() {
return key;
}

public boolean isExpired() {
return System.currentTimeMillis() > expirationTimestamp;
}
}

现在 map 的类型是 Map<ExpiringKey<K>, V>一些特定的 KV类型值。后台线程可以使用 Runnable 表示类似于以下内容:
public class ExpiredKeyRemover implements Runnable {

private final Map<ExpiringKey<?>, ?> map;

public ExpiredKeyRemover(Map<ExpiringKey<?>, ?> map) {
this.map = map;
}

@Override
public void run() {
Iterator<ExpiringKey<?>> it = map.keySet().iterator();
while (it.hasNext()) {
if (it.next().isExpired()) {
it.remove();
}
}
}
}

然后是 Runnable可以启动,以便使用 ScheduledExecutorService 以固定间隔执行如下(这将每 5 秒清理一次 map ):
Map<ExpiringKey<K>, V> myMap = // ...

ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.scheduleAtFixedRate(new ExpiredKeyRemover(myMap), 0, 5, TimeUnit.SECONDS);

需要注意的是 Map用于 myMap 的实现必须同步或允许并发访问。并发的挑战 Map实现是 ExpiredKeyRemover可能会看到与客户端不同的 map View ,如果清理线程没有完成删除其他键(即使它已经删除了所需/过期的键,因为它的更改可能没有),则可能会将过期的键返回给客户端尚未提交)。此外,上述去除 key 的代码可以使用流来实现,但上述代码仅用于说明逻辑,而不是提供高性能实现。

希望有帮助。

关于java - 自*第一次*插入以来,Java中是否有一个过期映射在一段时间后使元素过期?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49560258/

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