前言
- 关于Guava LocalCache的存储可见Guava LocalCache源码分析:LocalCache生成
- 关于LocalCache的get、put、expand可见Guava LocalCache源码分析:LocalCache的get、put、expand、refresh、remove、clear、cleanUp(一)
refresh
LocalCache虽然可设置定时刷新,但其刷新机制更像为一种“懒刷新”。LocalCache的刷新接口scheduleRefresh与refresh,仅在子实现类的refresh方法被调用时调用或者在Entry被get时调用,即LocalCache本身并未设置额外线程对Entry进行更新,Entry的过期机制同理。其中,Entry被读取时的调用逻辑可见前篇。
LocalCache的段内Entry刷新过程如下:
V scheduleRefresh(
ReferenceEntry<K, V> entry,
K key,
int hash,
V oldValue,
long now,
CacheLoader<? super K, V> loader) {
//如果有设置更新时长,且已经过了更新时长,且值不是正在加载中
if (map.refreshes()
&& (now - entry.getWriteTime() > map.refreshNanos)
&& !entry.getValueReference().isLoading()) {
//更新值并返回新值
V newValue = refresh(key, hash, loader, true);
if (newValue != null) {
return newValue;
}
}
return oldValue;
}
@CanIgnoreReturnValue
@CheckForNull
V refresh(K key, int hash, CacheLoader<? super K, V> loader, boolean checkTime) {
//为需要更新的hash-key申请加载引用,如果没申请到(即返回为null)则证明该值正在加载中,即不需要再刷新
final LoadingValueReference<K, V> loadingValueReference =
insertLoadingValueReference(key, hash, checkTime);
if (loadingValueReference == null) {
return null;
}
//异步刷新
ListenableFuture<V> result = loadAsync(key, hash, loadingValueReference, loader);
if (result.isDone()) {
try {
//阻塞直到返回结果,该过程不可被打断(即不可被打断的future.get)
return Uninterruptibles.getUninterruptibly(result);
} catch (Throwable t) {
//错误已被记录,故无需重记录