前言
Guava Cache 一简单实用中,了解了两种创建方式,以及缓存加载的实用,这篇研究一下缓存淘汰删除策略。
Guava Cache 缓存数据删除
Guava Cache 缓存数据删除提供了分为主动删除和被动删除
被动删除类似redis中的删除策略,数据超过某个维度后我们要自己删除一些不常用的或者比较大的数据等等。
主动删除即我们自己调用api在程序中删除。
主动删除
- 1 基于数据大小删除
- 2 基于过期时间删除
- 3 基于引用删除
被动删除
- 单独删除
- 批量删除
- 删除所有
代码实践
被动删除
基于数据大小删除
首先来将缓存大小设置为3 然后加载一下缓存数据。
LoadingCache<String, Object> cache = CacheBuilder.newBuilder()
//最大缓存个数 3
.maximumSize(3).build(new CacheLoader<String, Object>() {
//读数据源 加载数据到缓存
@Override
public String load(String s) throws Exception {
return hm.get(s) + "";
}
});
加载缓存 超过最大长度3后继续往里面加数据
/* 初始化cache */
initCache(cache);
displayCache(cache);
System.out.println("=============================");
get(4 + "",cache);
displayCache(cache);
结果如下
可以看到在没有访问的情况下,key为1的数据被淘汰了,原数据顺序是123,添加4之后 1 没了;
在没有任何数据访问的前提下,淘汰策略是先进先出fifo。
然后我们来访问一下数据
/* 初始化cache */
initCache(cache);
displayCache(cache);
System.out.println("=============================");
读取缓存中的1的数据 缓存没有就返回Null
System.out.println(cache.getIfPresent("1"));
// CacheLoader 在创建cache对象时,采用CacheLoader来获取数据,当缓存不存在时能够自动加载数据到缓存中。
// 1 2 3 134
System.out.println("=============================");
get(4+"",cache);
displayCache(cache);
System.out.println("=============================");
get(5+"",cache);
displayCache(cache);
可以看到在访问 数据key是1之后 再添加Key是4的数据 后 淘汰掉了key为2的数据,在访问key是5数据后,原数据中没有,添加到缓存中,淘汰了key为3的数据。
可以理解为先访问数据key存在在原数据中后,再添加新数据,被访问的key会称为已到头部即lru策略,没被访问的数据会先进先出也就是fifo。
淘汰策略:lru + fifo
在访问次数一样的情况下 fifo淘汰数据
基于过期时间的删除
基于过期时间的删除分为两种:写多长时间后删除,读多长时间后删除
读多长时间后删除
LoadingCache<String, Object> cache = CacheBuilder.newBuilder()
//最大缓存个数 3
.maximumSize(3).expireAfterAccess(3, TimeUnit.SECONDS).build(new CacheLoader<String, Object>() {
//读数据源 加载数据到缓存
@Override
public String load(String s) throws Exception {
return hm.get(s) + "";
}
});
initCache(cache);
Thread.sleep(1000);
//访问1 1被访问
cache.getIfPresent("1");
displayCache(cache);
//歇了2.1秒
Thread.sleep(2100);
//最后缓存中会留下1
System.out.println("==================================");
displayCache(cache);
Thread.sleep(1100);
displayCache(cache);
System.out.println("=============================");
可以看到,访问1后停止2.1后总时间超过3s后 key为2,3的数据已经被删除,1还存在,再1.1s后 key是1的数据也被删除。
写多长时间后删除
LoadingCache<String, Object> cache = CacheBuilder.newBuilder()
//最大缓存个数 3
.maximumSize(3).expireAfterWrite(3, TimeUnit.SECONDS).build(new CacheLoader<String, Object>() {
//读数据源 加载数据到缓存
@Override
public String load(String s) throws Exception {
return hm.get(s) + "";
}
});
initCache(cache);
Thread.sleep(1000);
//访问1 1被访问
cache.getIfPresent("1");
displayCache(cache);
//歇了2.1秒
Thread.sleep(2100);
//最后缓存中会留下1
System.out.println("==================================");
displayCache(cache);
可以看到,无论是否访问数据只要超过3s都被删除
基于引用的删除
可以通过weakKeys和weakValues方法指定Cache只保存对缓存记录key和value的弱引用。这样当没有
其他强引用指向key和value时,key和value对象就会被垃圾回收器回收。
LoadingCache<String, Object> cache = CacheBuilder.newBuilder()
//最大缓存个数 3
.maximumSize(3).weakValues().build(new CacheLoader<String, Object>() {
@Override
public String load(String s) throws Exception {
return hm.get(s) + "";
}
});
Object value = new Object();
cache.put("1",value);
value = new Object(); //原对象不再有强引用
// 强制垃圾回收
System.gc();
System.out.println(cache.getIfPresent("1"));
可以看到保存在cache中的对象已经被回收
主动删除
将key=1 删除
cache.invalidate(“1”);
将key=1和2的删除
cache.invalidateAll(Arrays.asList(“1”,“2”));
清空缓存
cache.invalidateAll();