介紹
Guava cache是本地緩存的一種實(shí)現(xiàn)。
Guava Cache與ConcurrentMap很相似考杉,但也不完全一樣矫付。最基本的區(qū)別是ConcurrentMap會(huì)一直保存所有添加的元素蹂空,直到顯式地移除俯萌。相對(duì)地,Guava Cache為了限制內(nèi)存占用上枕,通常都設(shè)定為自動(dòng)回收元素咐熙。在某些場(chǎng)景下,盡管LoadingCache 不回收元素姿骏,它也是很有用的糖声,因?yàn)樗鼤?huì)自動(dòng)加載緩存。
應(yīng)用場(chǎng)景
- 對(duì)讀取性能要求高分瘦,空間換時(shí)間蘸泻,愿意消耗一定的內(nèi)存空間來(lái)提高讀取速度
- 預(yù)測(cè)到會(huì)存在熱數(shù)據(jù),會(huì)進(jìn)行頻繁的讀取操作
- 緩存數(shù)據(jù)不會(huì)超過(guò)內(nèi)存容量
(Guava Cache是單個(gè)應(yīng)用運(yùn)行時(shí)的本地緩存嘲玫。它不把數(shù)據(jù)存放到文件或外部服務(wù)器悦施。如果這不符合你的需求,請(qǐng)嘗試Memcached去团、Redis這類(lèi)工具)
注:如果你不需要Cache中的特性抡诞,使用ConcurrentHashMap有更好的內(nèi)存效率
如何使用
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);
結(jié)果:
a
null
LoadCache
示例2:
//模擬數(shù)據(jù)源
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("從源數(shù)據(jù)加載:"+s);
String s1 = map.get(s);
return StringUtils.isBlank(s1) ? "" : s1;//Q1.注:此處需判空,不能返回null土陪,會(huì)報(bào)錯(cuò)
}
});
String a = loadingCache.get("a");
System.out.println(a);
a = loadingCache.get("a");
System.out.println("測(cè)試本地緩存讀取:"+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);
//測(cè)試最大容量
a = loadingCache.get("a");
System.out.println("測(cè)試最大容量,從源數(shù)據(jù)讀取:"+a);
Thread.sleep(10000);
//測(cè)試過(guò)期回收
String a2 = loadingCache.get("a");
System.out.println("測(cè)試過(guò)期回收,從源數(shù)據(jù)讀取:"+a2);
}
運(yùn)行結(jié)果:
com.google.common.cache.CacheLoader$InvalidCacheLoadException: CacheLoader returned null for key c.
拋出異常昼汗,原因是讀取"c"時(shí)沒(méi)有值,從CacheLoader加載源數(shù)據(jù)到本地緩存返回為null鬼雀,所以我們需要在CacheLoader的load方法里增加空判斷( Q1處),不能返回null顷窒。
增加判空后:
從源數(shù)據(jù)加載:a
a
測(cè)試本地緩存讀取:a
從源數(shù)據(jù)加載:b
b
從源數(shù)據(jù)加載:c
從源數(shù)據(jù)加載:a
測(cè)試最大容量,從源數(shù)據(jù)讀取:a
從源數(shù)據(jù)加載:a
測(cè)試過(guò)期回收,從源數(shù)據(jù)讀取:a