介绍
Guava cache是本地缓存的一种实现。
Guava Cache与ConcurrentMap很相似,但也不完全一样。最基本的区别是ConcurrentMap会一直保存所有添加的元素,直到显式地移除。相对地,Guava Cache为了限制内存占用,通常都设定为自动回收元素。在某些场景下,尽管LoadingCache 不回收元素,它也是很有用的,因为它会自动加载缓存。
应用场景
- 对读取性能要求高,空间换时间,愿意消耗一定的内存空间来提高读取速度
- 预测到会存在热数据,会进行频繁的读取操作
- 缓存数据不会超过内存容量
(Guava Cache是单个应用运行时的本地缓存。它不把数据存放到文件或外部服务器。如果这不符合你的需求,请尝试Memcached、Redis这类工具)
注:如果你不需要Cache中的特性,使用ConcurrentHashMap有更好的内存效率
如何使用
pom依赖
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>20.0</version>
</dependency>
Cache
示例:
Cache<String, String> cache = CacheBuilder.newBuilder()
.maximumSize(2)
.expireAfterWrite(10, TimeUnit.SECONDS)
.build();
cache.put("a","a");
String a = cache.getIfPresent("a");
Thread.sleep(10000);
String a2 = cache.getIfPresent("a");
System.out.println(a);
System.out.println(a2);
结果:
a
null
LoadCache
示例2:
//模拟数据源
public static ConcurrentHashMap<String, String> map=new ConcurrentHashMap<String, String>();
{
map.put("a", "a");
map.put("v", "v");
map.put("b", "b");
map.put("d", "d");
map.put("f", "f");
map.put("e", "e");
}
@Test
void createGuavaLoadCache() throws Exception{
LoadingCache<String, String> loadingCache = CacheBuilder.newBuilder()
.maximumSize(2)
.expireAfterWrite(10, TimeUnit.SECONDS)
.build(new CacheLoader<String, String>() {
@Override
public String load(String s) throws Exception {
System.out.println("从源数据加载:"+s);
String s1 = map.get(s);
return StringUtils.isBlank(s1) ? "" : s1;//Q1.注:此处需判空,不能返回null,会报错
}
});
String a = loadingCache.get("a");
System.out.println(a);
a = loadingCache.get("a");
System.out.println("测试本地缓存读取:"+a);
String b = loadingCache.get("b");
System.out.println(b);
String c = loadingCache.get("c");
System.out.println(c);
c = loadingCache.get("c");
System.out.println(c);
//测试最大容量
a = loadingCache.get("a");
System.out.println("测试最大容量,从源数据读取:"+a);
Thread.sleep(10000);
//测试过期回收
String a2 = loadingCache.get("a");
System.out.println("测试过期回收,从源数据读取:"+a2);
}
运行结果:
com.google.common.cache.CacheLoader$InvalidCacheLoadException: CacheLoader returned null for key c.
抛出异常,原因是读取"c"时没有值,从CacheLoader加载源数据到本地缓存返回为null,所以我们需要在CacheLoader的load方法里增加空判断( Q1处),不能返回null。
增加判空后:
从源数据加载:a
a
测试本地缓存读取:a
从源数据加载:b
b
从源数据加载:c
从源数据加载:a
测试最大容量,从源数据读取:a
从源数据加载:a
测试过期回收,从源数据读取:a
网友评论