Ali*_*aka 4 java caching dictionary expirationhandler
我尝试查看缓存机制,例如 Guava 的Cache
. 它们的有效期仅自上次更新以来。
我正在寻找的是一种数据结构,它存储密钥并在第一次插入后经过一段时间后清理密钥。我正计划将该值设为某个计数器。
一个场景可能是一个沉默的工人,他第一次做一些工作,但在一段时间内保持沉默 - 即使需要工作。如果在到期时间过后要求工作,他将完成工作。
知道这样的数据结构吗?谢谢。
为此,有几个选项。
被动移除
如果不需要在过期键一过期或按设定的时间间隔清除过期的键(即当键过期或在某个设定的时间间隔内不需要删除键),那么来自 Apache Commons Collections 的PassiveExpiringMap是一个不错的选择。尝试访问此映射中的密钥时,将检查该密钥的生存时间 (TTL)(所有密钥具有相同的 TTL),如果该密钥已过期,则将其从映射中删除并null
返回。这个数据结构并不能拥有有效的清理机制,使过期当对应于该键的TTL已过期后,他们正在访问的条目只删除。
缓存
如果需要更多基于缓存的功能(例如最大缓存容量和添加/删除侦听),Google Guava 提供了CacheBuilder类。这个类比 Apache Commons 替代方案更复杂,但它也提供了更多的功能。如果这旨在用于更多基于缓存的应用程序,那么这种权衡可能是值得的。
螺纹拆卸
如果需要主动删除过期密钥,则可以生成一个单独的线程来负责删除过期密钥。在查看可能的实现结构之前,应该注意这种方法的性能可能低于上述替代方案。除了启动线程的开销外,线程可能会导致与访问地图的客户端发生争用。例如,如果客户端想要访问一个键并且清理线程当前正在删除过期的键,则客户端将阻塞(如果使用同步)或具有不同的映射视图(包含哪些键值对)在地图中)如果采用了某种并发机制。
话虽如此,使用这种方法很复杂,因为它需要将 TTL 与密钥一起存储。一种方法是创建一个ExpiringKey
,例如(每个键可以有自己的 TTL;即使所有键最终都具有相同的 TTL 值,这种技术不需要创建Map
装饰器或Map
接口的其他实现) :
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;
}
}
Run Code Online (Sandbox Code Playgroud)
现在地图的类型将Map<ExpiringKey<K>, V>
具有一些特定的K
和V
类型值。可以使用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();
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后Runnable
可以启动它,以便它使用 aScheduledExecutorService
以固定间隔执行,如下所示(这将每 5 秒清理一次地图):
Map<ExpiringKey<K>, V> myMap = // ...
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.scheduleAtFixedRate(new ExpiredKeyRemover(myMap), 0, 5, TimeUnit.SECONDS);
Run Code Online (Sandbox Code Playgroud)
需要注意的是,Map
用于的实现myMap
必须同步或允许并发访问。并发Map
实现的挑战在于,如果清理线程没有完成删除其他键(即使它已经删除了所需的键),它ExpiredKeyRemover
可能会看到与客户端不同的映射视图,并且可能会将过期的键返回给客户端。 /expired 密钥,因为其更改可能尚未提交)。此外,上述去除密钥的代码可以使用流来实现,但上述代码仅用于说明逻辑,而不是提供高性能实现。
希望有帮助。
归档时间: |
|
查看次数: |
8873 次 |
最近记录: |