看了官方的关于Guava Cache的介绍,感觉太过于啰嗦,我个人是很不喜欢,看了好大半天也看不懂,直到翻到了一篇国内的文章才看懂,特此记录,以备查阅。
如何使用CacheCache<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()); //获取统计信息
LoadingCache
LoadingCache是Cache的子接口,相比较于Cache,当从LoadingCache中读取一个指定key的记录时,如果该记录不存在,则LoadingCache可以自动执行加载数据到缓存的操作。
LoadingCache的使用
LoadingCache<String, String> cache = CacheBuilder.newBuilder()
.build(
new CacheLoader<String, String>() {
@Override
public String load(String key) throws Exception {
//在这里可以初始化加载数据的缓存信息,读取数据库中信息或者是加载文件中的某些数据信息
return "";
}
});
与构建Cache类型的对象类似,LoadingCache类型的对象也是通过CacheBuilder进行构建,不同的是,在调用CacheBuilder的build方法时,必须传递一个CacheLoader类型的参数,CacheLoader的load方法需要我们提供实现。当调用LoadingCache的get方法时,如果缓存不存在对应key的记录,则CacheLoader中的load方法会被自动调用从外存加载数据,load方法的返回值会作为key对应的value存储到LoadingCache中,并从get方法返回。
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);//在构建时指定自动加载器
或者也可以结合spring来用
@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;