一.概述
在上篇文章《Guava Cache做本地缓存那些事》中我介绍了Guava Cache作为本地缓存的一般用法,叙述了构造LoadingCache的方式和其基本使用,以及两种get方法的区别,LoadingCache和Cache的区别等内容。而为了知其然并知其所以然,本文对Guava Cache的实现原理做一些简单介绍,如有不对的地方请大家批评指正。
首先,先把Guava Cache在github上的源码链接放出来。里面有作者写的注释,可以方便大家学习。
Guava Cache带注释源码
二.关注的问题
从上述源码和前一篇介绍Guava Cache用法的文章中大家可以看出Guava Cache涉及的类和代码还是比较多的,如果挨个文件去分析涉及的细节太多,不容易把握关键的问题。所以笔者决定从get方法的执行过程出发对Guava Cache的原理进行分析。分析主要关注以下三个问题:
- Guava Cache是如何通过key映射到value的;
- 未命中缓存时如何调用的CacheLoader.load方法来载入缓存的;
- 两种缓存失效策略是如何实现的。
三.源码分析
3.1 key-value的映射过程
通过以下例子我们来看一下key-value的映射过程:
public static void demo1() throws Exception {
//定义Cache,并定义未命中时的载入方法
LoadingCache<Integer, Integer> cache = CacheBuilder.newBuilder().build(new CacheLoader<Integer, Integer>() {
@Override
public Integer load(Integer key) throws Exception {
return key + 1;
}
});
cache.get(1); //第一个get:第一次访问key,使用载入方法载入
cache.get(1); //第二个get:第二次访问,在缓存中得到value
}
以上demo定义了一个LoadingCache,并传入了CacheLoader提供在未命中缓存时的处理方法。后面可以看到对get方法调用了两次,第一次是为了通过load方法将相应的value载入缓存,这个过程在3.2节中介绍。本节主要看一下第二次get的过程:在缓存中存在对应value的情况下,如何通