并没有深刻的理解,只是mark下结论.
- expireAfterAccess
在指定的过期时间内没有读写,缓存数据即失效 - expireAfterWrite
在指定的过期时间内没有写入,缓存数据即失效 - refreshAfterWrite
在指定的过期时间之后访问时,刷新缓存数据,在刷新任务未完成之前,其他线程返回旧值.
expireAfterAccess,expireAfterWrite在数据过期时,都会删除缓存数据,然后委派当前线程去加载新的数据,其他的线程访问key的时候会阻塞,直到加载完新的数据,一起返回.
refreshAfterWrite在刷新缓存数据时,也会委派当前线程去加载新的数据,但是其他线程在访问这个key的时候,会直接返回旧的值,而不是等待,阻塞.但是总是有一个线程是阻塞的,重写reload方法,可以把加载数据的任务交给其他线程.区别就是,在刷新数据时,访问这个key的所有的线程都会直接返回旧值,不会有任何一个线程阻塞,且返回的数据是一致的.
代码如下:
private final LoadingCache<String, Map<String, RoomV2>> liveReceptionStarCache = CacheBuilder.newBuilder()
.refreshAfterWrite(1, TimeUnit.SECONDS)
.maximumSize(200)
.build(CacheLoader.asyncReloading(new CacheLoader<String, Map<String, RoomV2>>() {
@Override
public Map<String, RoomV2> load(String s) throws Exception {
return getData();
}
@Override
public ListenableFuture<Map<String, RoomV2>> reload(String key, Map<String, RoomV2> oldValue) throws Exception {
return super.reload(key, oldValue);
}
}, executor));
个人认为,如果key会被频繁修改并且对key的更新非常敏感,最好的做法是配置refreshAfterWrite参数,并重写reload方法.如果不重写reload方法,总是有一个线程是会被阻塞的.
参考:
https://albenw.github.io/posts/df42dc84/