前言
上篇文章,详细描写了Guava LocalCache怎样如JDK7的ConcurrentHashMap对缓存数据进行了分段存储。本章主要针对LocalCache重要的几个接口进行说明。
一、get
@CanIgnoreReturnValue
@Override
@CheckForNull
public V get(@CheckForNull Object key) {
if (key == null) {
return null;
}
int hash = hash(key);
return segmentFor(hash).get(key, hash);
}
@CanIgnoreReturnValue
V get(K key, CacheLoader<? super K, V> loader) throws ExecutionException {
int hash = hash(checkNotNull(key));
return segmentFor(hash).get(key, hash, loader);
}
如上代码,LocalCache的get方法首先根据key计算出hash值,并根据hash值找到对应的segment,再调用segment的get方法获取最终结果。
以传入loader参数的get方法为例,看一下segment如何获取值的。
@CanIgnoreReturnValue
V get(K key, int hash, CacheLoader<? super K, V> loader) throws ExecutionException {
checkNotNull(key);
checkNotNull(loader);
try {
if (count != 0) {
//不要调用getLiveEntry,这将忽略正在加载的值
//根据key和hash获取值
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);
//累计命中+1,这里Guava似乎认为当多条线程在更新统计数据时,
//而不是细粒度同步控制的情况下,LongAdder比AtomicLong更好用。
statsCounter.recordHits(1);
//检查是否需要刷新,如果设置了刷新时长且过了刷新时长,则刷新,否则返回该值
return scheduleRefresh(e, key, hash, value, now, loader);
}
//值已经过期
ValueReference<K, V> valueReference = e.getValueReference()