为什么会有guava cache
实际开发中,有时候会有一些不常修改,但是经常会被用到的数据,它们可能放在数据库里,也可能放在配置文件等。每次用到它们,如果都去查数据库,读取配置文件的话,那么效率是比较慢的。我们可以把数据集中放到一个地方,每次查询的时候就去那个地方查。这个地方可以是redis,相比查数据库,redis效率显然会更快,但是还是得跨网络。这个地方也可以是JVM内存,在所有的存放数据的地方中,内存无疑是最快的。存放数据,又是jvm内存,你可能会想到HashMap,如果是比较简单的需求,HashMap已经满足我们的需求了;但是如果你存放数据的同时,又要求可能像redis一样可以设置过期时间,还要求一定要线程安全,这时候HashMap可能就有点力不从心了。而guava cache就是这样一款可以把数据存放到JVM内存,还具有设置过期时间等功能的缓存工具。
guava cache
你可以把 guava cache当做一个可以设定过期机制,多线程安全的map;实际上,guava cache底层的LocalCache也确实是继承了ConcurrentMap。
class LocalCache extends AbstractMap implements ConcurrentMap {
...
}
pom文件
com.google.guava
guava
23.0
java代码
public static void main(String[] args) throws Exception {
LoadingCache cache = CacheBuilder.newBuilder()
.build(new CacheLoader() {
@Override
public Object load(String key) throws Exception {
return getValue(key);
}
});
System.out.println("key.length = " + cache.get("hello"));
}
private static Object getValue(String key) {
return key.length();
}
利用CacheBuilder.newBuilder().build(new CacheLoader(){...})即可创建一个LocalCache,build里面的new CacheLoader(){...}是根据key加载获取value的方式,我们可以调取rmi加载获取相关信息,也可以从数据库加载获取信息,还可以从配置文件加载获取信息,获取到value以后,LocalCache会把数据保存到内存中,如果第二次获取该key的数据的话,直接从内存中读取数据返回,而不用再次加载了。我这里做演示用,所以只是保存了key的长度。
加载与插入
guava cache和hashMap最大的不同就是,hashMap想要get某个key对应的value的时候,要先显式把value put进去,但是guava cache有一个加载机制,在创建LocalCache或者get 的时候传入CacheLoader或者Callable实例,每次我们get,guava cache会首先从cache里面查找是否有key对应的value,如果有,返回,如果没有,会调用LocalCache或者callable加载key对应的value,然后隐式的put到cache中并且返回,从而我们不用先显式把value put 进去。
- CacheLoader
public static void main(String[] args) throws Exception {
LoadingCache cache = CacheBuilder.newBuilder()
.build(new CacheLoader() {
@Override
public Object load(String key) throws Exception {
return getValue(key);
}
});
一般我们可以通过cache.get(key)来获取key对应的value,但是这个办法会抛出ExecutionException 的异常,如果我们不想每次都写个try catch来处理ExecutionException ,我们可以用cache.getUnchecked(key),如果用getUnchecked,CacheLoader加载器中不要声明任何检查型异常;批量获取可以用getAll(Iterable)。
- Callable
Cache cache = CacheBuilder.newBuilder().build();
cache.put("hello", "hi");
System.out.println(cache.get("hello", new Callable