Guava Cache缓存机制有两个基本的接口:Cache和LoadingCache,LoadingCache接口继承自Cache接口,本篇我们首先来学习Cache接口。
Cache接口提供了键和值的映射,实现这个类是线程安全的,可以用于并发。
put(K key, V value)
这个方法主要是进行赋值,如果插入一个键值对,对于同一个Key,新的value将替代老的value.
V get(K key, Callable extends V> loader)
返回与此key关联的值,该方法改进了传统的“if cached, return” 或“create, cache and return”模式。更好的建议,可以采纳LoadingCache中的V get(K key)
方法。
V value = cache.get(key, Callable Extends V> value);
上面的方法会检索当前的value值,如果值不存在的话会从Callback实例中提取value值,通过key关联value,并返回相应的value值,它为我们提供了通过调用一个方法来替代下面风格的编程:
value = cache.get(key);
if(value == null){
value = someService.retrieveValue();
cache.put(key,value);
}
LoadingCache是一个接口类,继承Cache。扩展了Cache接口的自动装载的功能。是线程安全的,可以用于多线程并发。
Book book = loadingCache.get(id);
在上面的代码中, 如果book对象在get方法调用执行的时候不可用,LoadingCache知道怎样返回对象,保存在缓存中,然后返回value值。
由于LoadingCache的实现是线程安全的,通过同样的key值调用get方法,当缓存还在装载的时候就会阻塞线程。一旦value值被加载,该调 用将返回最原始的调用get方法返回的value值,然而,多个通过不同key值的调用则会并发的加载,如果我们拥有一个键值的集合,并且想要去检索每个 键对应的value值,我们需要像下面这样调用:
ImmutableMap<key,value> map = cache.getAll(Iterable<? Extends key>);
如上所示,getAll方法返回了一个不可变的Map集合,通过指定键值以及与键值关联的缓存中的value值,getAll返回的map可能是所有缓存的value值,也可能是新检索到的value值,或者是已有缓存和新检索到的value值的混合。
LoadingCache 同样提供了一种缓存中更新value值的机制:
void refresh(K key)
通过调用refresh方法,LoadingCache会检索到对应key新的value值,当前的value值在新的value值返回前不会被从缓存出 废弃,这意味着如果在加载的过程中调用get方法,则会返回缓存中当前的value值。如果在refresh方法调用中出现异常,原始的value值会依 然在缓存中保存。需要记住的是:如果value值被异步的检索,在value值被真正的更新前,方法都将会返回原始的value值。