Guava Cache 是Google Fuava中的一个内存缓存模块,用于将数据缓存到JVM内存中。
通常,Guava缓存适用于以下情况:
com.google.guava
guava
29.0-jre
下面配合缓存的清除策略实现代码逻辑:
public class TestController {
private static final Cache TEST_CACHE = CacheBuilder.newBuilder()
// 设置缓存容量数
.maximumSize(2)
.build();
public static void main(String[] args) {
TEST_CACHE.put("1","a1");
TEST_CACHE.put("2","a2");
TEST_CACHE.put("3","a3");
System.out.println(TEST_CACHE.getIfPresent("1"));
System.out.println(TEST_CACHE.getIfPresent("2"));
System.out.println(TEST_CACHE.getIfPresent("3"));
}
}
输出:
null
a2
a3
Process finished with exit code 0
解释:当我们把缓存最大数设置成2时,意为当前cache的key最多存2个,超过两个会把最开始添加的那一个去掉,所以我们第一个key获取值为null。
有两种一种是:写入缓存后多久过期;另一种是:读写缓存后多久到期
第一种 写入缓存后多久过期:
private static final Cache TEST_CACHE = CacheBuilder.newBuilder()
// 写缓存后多久过期
.expireAfterWrite(3, TimeUnit.SECONDS)
.build();
public static void main(String[] args) throws InterruptedException {
TEST_CACHE.put("1","a1");
// 睡2秒
Thread.sleep(2 * 1000);
System.out.println(TEST_CACHE.getIfPresent("1"));
// 睡2秒
Thread.sleep(2 * 1000);
System.out.println(TEST_CACHE.getIfPresent("1"));
}
a1
null
Process finished with exit code 0
解释:当我们把时间设置为写入缓存3秒后到期,可以看到当key为1的值在两秒后是可以获取到的,但在四秒后就获取不到了,因为这个key的有效期只有三秒。
思考:倘若我们在两秒后对当前的key进行了修改,经过四秒这个key还能获取到值吗?
代码:
private static final Cache TEST_CACHE = CacheBuilder.newBuilder()
// 写缓存后多久过期
.expireAfterWrite(3, TimeUnit.SECONDS)
.build();
public static void main(String[] args) throws InterruptedException {
TEST_CACHE.put("1","a1");
// 睡2秒
Thread.sleep(2 * 1000);
System.out.println(TEST_CACHE.getIfPresent("1"));
TEST_CACHE.put("1","a1-修改");
// 睡2秒
Thread.sleep(2 * 1000);
System.out.println(TEST_CACHE.getIfPresent("1"));
// 睡2秒
Thread.sleep(2 * 1000);
System.out.println(TEST_CACHE.getIfPresent("1"));
}
输出:
a1
a1-修改
null
Process finished with exit code 0
解释:我们看到,两秒后对当前key修改后,又经过两秒是可以获取修改后的值,但是又经过两秒,就获取不到值了。
由此得出结论,expireAfterWrite是写入多久并且没有再次更新当前key的值,那么值就会失效。
第二种 读写缓存后多久到期:
private static final Cache TEST_CACHE = CacheBuilder.newBuilder()
// 读写缓存后多久过期
.expireAfterAccess(3, TimeUnit.SECONDS)
.build();
public static void main(String[] args) throws InterruptedException {
TEST_CACHE.put("1","a1");
// 睡2秒
Thread.sleep(2 * 1000);
System.out.println(TEST_CACHE.getIfPresent("1"));
// 睡2秒
Thread.sleep(2 * 1000);
System.out.println(TEST_CACHE.getIfPresent("1"));
// 睡4秒
Thread.sleep(4 * 1000);
System.out.println(TEST_CACHE.getIfPresent("1"));
}
输出:
a1
a1
null
Process finished with exit code 0
解释:每隔两秒获取是可以获取到值,但是隔四秒去获取就获取不到了
由此我们可以得出结论,expireAfterAccess是多久没有访问当前key,那么这个key的值就会在设置的时间后过期。
private static final Cache TEST_CACHE = CacheBuilder.newBuilder()
.initialCapacity(10)
.build();
public static void main(String[] args) throws InterruptedException {
TEST_CACHE.put("1", "2");
TEST_CACHE.put("2", "1");
TEST_CACHE.put("3", "3");
System.out.println(TEST_CACHE.getIfPresent("1"));
System.out.println(TEST_CACHE.getIfPresent("2"));
System.out.println(TEST_CACHE.getIfPresent("3"));
// 清除单个
TEST_CACHE.invalidate("1");
System.out.println(TEST_CACHE.getIfPresent("1"));
// 清除多个
// TEST_CACHE.invalidateAll();
ArrayList list = Lists.newArrayList("2", "3");
TEST_CACHE.invalidateAll(list);
System.out.println(TEST_CACHE.getIfPresent("2"));
System.out.println(TEST_CACHE.getIfPresent("3"));
}
还有基于引用的清楚策略和基于权重的清除策略
有兴趣自学,上面三种已经能应对90%的问题了。注意这些策略都是可以搭配一起使用的。