缘起
看了官方的关于Guava Cache的介绍,感觉太过于啰嗦,我个人是很不喜欢,看了好大半天也看不懂,直到翻到了一篇国内的文章才看懂,特此记录,以备查阅。
如何使用Cache
Cache<String,String> cache = CacheBuilder.newBuilder().build();
public void test() {
cache.put("word","Hello Guava Cache");
System.out.println(cache.getIfPresent("word"));
}
看到Cache非常类似于JDK中的Map,但是相比于Map,Guava Cache提供了很多更强大的功能。
自动加载
Cache的get方法有两个参数,第一个参数是要从Cache中获取记录的key,第二个记录是一个Callable对象。当缓存中已经存在key对应的记录时,get方法直接返回key对应的记录。如果缓存中不包含key对应的记录,Guava会启动一个线程执行Callable对象中的call方法,call方法的返回值会作为key对应的值被存储到缓存中,并且被get方法返回。Guava可以保证当有多个线程同时访问Cache中的一个key时,如果key对应的记录不存在,Guava只会启动一个线程执行get方法中Callable参数对应的任务加载数据存到缓存。当加载完数据后,任何线程中的get方法都会获取到key对应的值。
String value = cache.get("key", new Callable<String>() {
public String call() throws Exception {
System.out.println("load1"); //加载数据线程执行标志
Thread.sleep(1000); //模拟加载时间
return "auto load by Callable";
}
});
设置最大存储
Cache<String,String> cache = CacheBuilder.newBuilder()
.maximumSize(2)
.build();
cache.put("key1","value1");
cache.put("key2","value2");
cache.put("key3","value3");
System.out.println("第一个值:" + cache.getIfPresent("key1"));
System.out.println("第二个值:" + cache.getIfPresent("key2"));
System.out.println("第三个值:" + cache.getIfPresent("key3"));
设置过期时间
在构建Cache对象时,可以通过CacheBuilder类的expireAfterAccess和expireAfterWrite两个方法为缓存中的对象指定过期时间,过期的对象将会被缓存自动删除。其中,expireAfterWrite方法指定对象被写入到缓存后多久过期,expireAfterAccess指定对象多久没有被访问后过期。
Cache<String,String> cache = CacheBuilder.newBuilder()
.maximumSize(2)
.expireAfterWrite(3,TimeUnit.SECONDS)
.build();
弱引用
可以通过weakKeys和weakValues方法指定Cache只保存对缓存记录key和value的弱引用。这样当没有其他强引用指向key和value时,key和value对象就会被垃圾回收器回收。
Cache<String,Object> cache = CacheBuilder.newBuilder()
.maximumSize(2)
.weakValues()
.build();
显示清除
可以调用Cache的invalidateAll或invalidate方法显示删除Cache中的记录。invalidate方法一次只能删除Cache中一个记录,接收的参数是要删除记录的key。invalidateAll方法可以批量删除Cache中的记录,当没有传任何参数时,invalidateAll方法将清除Cache中的全部记录。invalidateAll也可以接收一个Iterable类型的参数,参数中包含要删除记录的所有key值。
Cache<String,String> cache = CacheBuilder.newBuilder().build();
Object value = new Object();
cache.put("key1","value1");
cache.put("key2","value2");
cache.put("key3","value3");
List<String> list = new ArrayList<String>();
list.add("key1");
list.add("key2");
cache.invalidateAll(list);//批量清除list中全部key对应的记录
监听器监听移除元素动作
可以为Cache对象添加一个移除监听器,这样当有记录被删除时可以感知到这个事件。
RemovalListener<String, String> listener = new RemovalListener<String, String>() {
public void onRemoval(RemovalNotification<String, String> notification) {
System.out.println("[" + notification.getKey() + ":" + notification.getValue() + "] is removed!");
}
};
Cache<String,String> cache = CacheBuilder.newBuilder()
.maximumSize(3)
.removalListener(listener)
.build();
统计信息
可以对Cache的命中率、加载数据时间等信息进行统计。在构建Cache对象时,可以通过CacheBuilder的recordStats方法开启统计信息的开关。开关开启后Cache会自动对缓存的各种操作进行统计,调用Cache的stats方法可以查看统计后的信息。
Cache<String,String> cache = CacheBuilder.newBuilder()
.maximumSize(3)
.recordStats() //开启统计信息开关
.build();
System.out.println(cache.stats()); //获取统计信息
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0gTMx81dsQWZ4lmZf1GLlpXazVmcvwFciV2dsQXYtJ3bm9CX9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5CO2UTN2czMjZGOwYjZwU2YxYzX0IDO1MDMxMzLcJTMxIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
LoadingCache
LoadingCache的使用
LoadingCache<String, String> cache = CacheBuilder.newBuilder()
.build(
new CacheLoader<String, String>() {
@Override
public String load(String key) throws Exception {
//在这里可以初始化加载数据的缓存信息,读取数据库中信息或者是加载文件中的某些数据信息
return "";
}
});
CacheLoader<String, String> loader = new CacheLoader<String, String> () {
public String load(String key) throws Exception {
Thread.sleep(1000); //休眠1s,模拟加载数据
System.out.println(key + " is loaded from a cacheLoader!");
return key + "'s value";
}
};
LoadingCache<String,String> loadingCache = CacheBuilder.newBuilder()
.maximumSize(3)
.build(loader);//在构建时指定自动加载器
@Bean
public LoadingCache<String, Object> myCacheStorage() {
return CacheBuilder.newBuilder()
.build(new CacheLoader<String, Object>() {
@Override
public Object load(String name) throws Exception {
//在这里可以初始化加载数据的缓存信息,读取数据库中信息或者是加载文件中的某些数据信息
return null;
}
});
}
@Autowired
LoadingCache<String, Object> loadingCache;