案例1:
PriceSourceSwitchHandler priceSourceSwitchHandler = new PriceSourceSwitchHandler();
Cache<String, String> linkStatusMap = CacheBuilder.newBuilder()
.expireAfterWrite(10, TimeUnit.SECONDS)
.removalListener(priceSourceSwitchHandler::resetLinkStatus)
.build();
linkStatusMap.put("1","1");
TimeUnit.SECONDS.sleep(12);
//linkStatusMap.cleanUp();
linkStatusMap.getIfPresent("1");
案例2:
LoadingCache<String, String> linkStatusMap = CacheBuilder.newBuilder()
// .expireAfterAccess(10, TimeUnit.SECONDS)
.expireAfterWrite(10, TimeUnit.SECONDS)
.refreshAfterWrite(5, TimeUnit.SECONDS)
.removalListener(priceSourceSwitchHandler::resetLinkStatus)
.build(new CacheLoader<String, String>() {
@Override
public String load(String s) throws Exception {
return "def";
}
@Override
public ListenableFuture<String> reload(String key, String oldValue) throws Exception {
return super.reload(key, oldValue);
}
});
linkStatusMap.put("1","1");
TimeUnit.SECONDS.sleep(12);
//linkStatusMap.cleanUp();
linkStatusMap.get("1");
注意点:
1.案例1中直接调用build()后得到的Cache接口,数据过期后在调用linkStatusMap.getIfPresent("1")发现removalListener不生效,但是数据确实删除了,缓存没了
2.案例2中直接调用build()后得到的Cache接口,数据过期后在调用linkStatusMap.get("1")发现可以触发removalListener
3.案例2中expireAfterAccess方法是在设置的时间内没有get、put相关操作,就会过期,但是数据还未删除,只有访问了(get、put)该数据才会真正删除该数据
4.案例2中expireAfterWrite方法是在设置的时间内没有put相关操作,就会过期,但是数据还未删除,只有访问了(get、put)该数据才会真正删除该数据,其中put会把当前segment下的所有数据删除,可参考:guava的loadingcache什么时候删除过期的数据? - 简书 (jianshu.com)
5.案例2中refreshAfterWrite方法是在设置的时间内没有put相关操作,就会重新reload,前提是该key必须调用过load方法;
如案例2中: 比如开始get("key"),会触发load,加载默认值def存入缓存("key","def"),这里load一次之后,后面才能触发reload;
5秒-10秒时间段内,比如7秒没有put操作,就会reload; 如果超过时间段,比如12秒没有put操作,则直接过期
6.过期数据不会自动删除,需要起个定时任务,调用 linkStatusMap.cleanUp()方法删除过期数据 ,会把所有segment下的所有数据删除
使用Guava中Cache的注意点
于 2023-06-27 16:41:00 首次发布