我在 Map
List<CompletableFuture>
private final Map<UUID, List<CompletableFuture>> hydrationProcesses = new ConcurrentHashMap<>();
当前有一个守护程序线程每30秒运行一次,并删除所有已完成的Futures
。
有很多TTL无效的实现,我正在寻找基于某些谓词的无效。我想摆脱这个守护程序。
是否有基于某些自定义逻辑的计划缓存无效的盒子解决方案。也许我错过了春季/番石榴的东西?
也许类似于Guava的
CacheBuilder.newBuilder()
.expireAfterAccess(2,TimeUnit.MILLISECONDS)
.build(loader);
,但是然后在访问后将所有内容都标记为已过期的所有内容,我需要检查此未来是否已经完成,然后将其从缓存中删除。
我怀疑是否有基于番石榴的解决方案。由于您不专门要求" guava--"解决方案,我想想一想如何解决cache2k的问题。
这是设置的外观:
final long RECHECK_INTERVAL_MILLIS = 30000;
Cache<UUID, CompletableFuture<Void>> cache =
new Cache2kBuilder<UUID, CompletableFuture<Void>>(){}
.loader(new AdvancedCacheLoader<UUID, CompletableFuture<Void>>() {
@Override
public CompletableFuture<Void> load(UUID key,
long currentTime,
CacheEntry<UUID, CompletableFuture<Void>> currentEntry) {
return currentEntry != null ? currentEntry.getValue() : null;
}
})
.expiryPolicy(new ExpiryPolicy<UUID, CompletableFuture<Void>>() {
@Override
public long calculateExpiryTime(UUID key,
CompletableFuture<Void> value,
long loadTime,
CacheEntry<UUID, CompletableFuture<Void>> oldEntry) {
return value.isDone() ? NOW : loadTime + RECHECK_INTERVAL_MILLIS;
}
})
.refreshAhead(true)
.build();
实际上Cache2k具有类似的功能,然后具有Guava或其他缓存。但是,有一些很小的扩展可以允许更复杂的设置。
这里使用的技巧是在通过操作中读取中的缓存,但使加载程序返回当前的高速缓存值。当条目到期后,由于refreshAhead(true)
而调用加载程序,但是保留了当前值并再次评估到期策略。您喜欢检查的谓词进入了到期政策。
其他缓存也已经阅读并定制到期,但缺乏"智能装载机"的概念。(AdvancedCacheLoader
(可以根据现有的高速缓存值更有效地行事。
我们在生产中使用与此相似的设置。
也有一个缺点。如果使用自定义有效期,则Cache2k使用每个缓存的一个计时线程。这意味着您的额外线程不会消失。将来将增强Cache2k,以在所有缓存中共享一套全局时间用于定时线程。更新: Cache2k的新版本使用计时器的公共线程池。
免责声明:我是cache2k的作者,所以我绝对不能确定基于guava的解决方案。