以下基于cacheLoader方式:
1.定时过期:expireAfterWrite
2.定时刷新:refreshAfterWrite + 重载reload
3.定时异步刷新:refreshAfterWrite + 重载reload + 线程池
共同点:
当key=null或expire时,都会加锁,并且以同步方式调用load方法加载数据。
不同点:
当key存活于cache中,过了刷新周期后,当有线程访问数据某key的数据时,会以同步或异步的方式调用reload方法加载数据,在加载数据的过程中,如果有请求过来需要获取该key的数据,此时,返回oldValue,并不会触发reload方法调用。
代码分析:
V get(K key, int hash, CacheLoader<? super K, V> loader) throws ExecutionException {
checkNotNull(key);
checkNotNull(loader);
try {
if (count != 0) { // read-volatile
// don't call getLiveEntry, which would ignore loading values
ReferenceEntry<K, V> e = getEntry(key, hash);
if (e != null) {
long now = map.ticker.read();
V value = getLiveValue(e, now);
if (value != null) {
recordRead(e, now);
statsCounter.recordHits(1);
return scheduleRefresh(e, key, hash, value, now, loader);//定时刷新逻辑,refresh
}
ValueReference<K, V> valueReference = e.getValueReference();
if (valueReference.isLoading()) {
return waitForLoadingValue(e, key, valueReference);
}
}
}
// at this point e is either null or expired;//key=null或者过期时,同步加载数据
return lockedGetOrLoad(key, hash, loader);
} catch (ExecutionException ee) {
Throwable cause = ee.getCause();
if (cause instanceof Error) {
throw new ExecutionError((Error) cause);
} else if (cause instanceof RuntimeException) {
throw new UncheckedExecutionException(cause);
}
throw ee;
} finally {
postReadCleanup();
}
}
参考例子:
http://blog.csdn.net/u012859681/article/details/75220605
参考文章:
http://blog.csdn.net/u012859681/article/details/75220605
http://blog.csdn.net/abc86319253/article/details/53020432
http://ifeve.com/google-guava-cachesexplained/
http://blog.csdn.net/zhangjikuan/article/details/76408578