gpt4 book ai didi

java - LoadingCache expireAfterWrite 未按预期工作

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:05:12 25 4
gpt4 key购买 nike

我有一个像这样的加载缓存:

MyCacheLoader loader=new MyCacheLoader();
MyRemovalListener listener=new MyRemovalListener();
LoadingCache<String, String> myCache = CacheBuilder.newBuilder()
.concurrencyLevel(10)
.weakKeys()
.maximumSize(2)
.expireAfterWrite(120, TimeUnit.SECONDS)
.removalListener(listener)
.build(loader);

但是当我做这样的事情来测试时:

System.out.println(myCache.get("100"));
System.out.println(myCache.get("103"));
System.out.println(myCache.get("110"));
System.out.println(myCache).get("111"));
Thread.sleep(230000);
System.out.println(myCache.size());

我仍然得到 2 而不是零。为什么 ?超过 120 秒后,如果我没记错的话,我的大小应该为零?

MyCacheLoader

public class MyCacheLoader extends CacheLoader<String,String>     {
@Override
public String load(String key) throws Exception {
return key;
}
}

MyRemovalListener

public class MyRemovalListener implements RemovalListener<String,String> {

Logger logger = LoggerFactory.getLogger(MyRemovalListener.class);
@Override
public void onRemoval(RemovalNotification<String, String> removalNotification) {
logger.info("Message with message Id ("+
removalNotification.getKey()+ ") is removed.");
System.out.println("Message with message Id ("+
removalNotification.getKey()+ ") is removed.");
}
}

最佳答案

首先,如果您不熟悉 Guava 的缓存 API,或者您将其视为实现了 Map<K, V>界面然后我建议阅读CachesExplained · google/guava Wiki . “CacheConcurrentMap 相似,但不完全相同。”

例如 Cache.size() Map.size() 不同,“返回此缓存中条目的近似值”(添加了强调)其中“返回此映射中键值映射的数量。”

因此,我们不应该期待 Cache.size()返回一个准确的条目数,但一个近似的条目数。我一般不会对 Cache.size() 做出断言虽然我肯定会在 Map.size() .

其次,“使用 CacheBuilder 构建的缓存不会‘自动’执行清理和逐出值,或者在值过期后立即执行,或任何类似的操作。相反,它执行少量的在写入操作期间进行维护,或者在写入操作很少的情况下在偶尔的读取操作期间进行维护”(When Does Cleanup Happen? · CachesExplained · google/guava Wiki)。

考虑以下示例:

LoadingCache<String, String> myCache = CacheBuilder.newBuilder()
.concurrencyLevel(10)
.weakKeys()
.maximumSize(2)
.expireAfterWrite(120, TimeUnit.MILLISECONDS)
.removalListener(notification ->
System.out.println(notification.getKey() + " removed"))
.build(new CacheLoader<String, String>() {
@Override
public String load(String key) throws Exception {
System.out.println("loading " + key);
return UUID.randomUUID().toString();
}
});
myCache.get("100");
myCache.get("103");
myCache.get("110");
myCache.get("111");
Thread.sleep(230);
System.out.println(myCache.size());
myCache.get("111");
System.out.println(myCache.size());

输出:

loading 100
loading 103
loading 110
100 removed
loading 111
103 removed
2
110 removed
111 removed
loading 111
1

如您所见,只有从缓存中读取项目后才会发生驱逐。

有关更多详细信息以及更详细的示例,请参阅 my answerHow does timed cache expiry work?

关于java - LoadingCache expireAfterWrite 未按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39386598/

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