我正在使用这样的加载缓存:
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.");
}
}
答案 0 :(得分:4)
首先,如果您不熟悉Guava的Cache API,或者如果您将其视为实现Map<K, V>
接口,那么我建议您阅读CachesExplained · google/guava Wiki。 “Cache
与ConcurrentMap
类似,但不完全相同。”
e.g。 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());
Ouptut:
loading 100
loading 103
loading 110
100 removed
loading 111
103 removed
2
110 removed
111 removed
loading 111
1
如您所见,在从缓存中读取项目之前,不会发生驱逐。
有关详细信息以及更详细的示例,请参阅my answer至How does timed cache expiry work?