Guava Cache與ConcurrentMap很類似基於分段鎖及線程安全,但也不徹底同樣。最基本的區別是ConcurrentMap會一直保存全部添加的元素,直到顯式地移除。相對地,Guava Cache爲了限制內存佔用,一般都設定爲自動回收元素。在某些場景下,儘管LoadingCache 不回收元素,它也是頗有用的,由於它會自動加載緩存。html
1)能夠接受消耗內存來提升性能java
2)某些key會被屢次查詢git
3)緩存中的數據量不會超出內存容量api
package com.guava.cache; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.Callable; import org.junit.Test; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.collect.Lists; /** * * @author gaojiayi * */ public class TestCache { //基於loadingCache加載 //@Test public void TestLoadingCache() throws Exception{ LoadingCache<String,String> cahceBuilder=CacheBuilder .newBuilder() .build(new CacheLoader<String, String>(){ //提供默認的加載加載方式,在實際生產中,能夠選擇從DB中,或者文件中加載相應的value @Override public String load(String key) throws Exception { String strProValue="hello "+key+"!"; return strProValue; } //批量加載 @Override public Map<String, String> loadAll(Iterable<? extends String> keys) throws Exception { // TODO Auto-generated method stub Map<String, String> retMap = new HashMap<String, String>(); for(String key: keys){ retMap.put(key, load(key)); } return retMap; } }); System.out.println("jerry value:"+cahceBuilder.apply("jerry")); //get(K)方法,這個方法要麼返回已經緩存的值,要麼使用CacheLoader向緩存原子地加載新值。 System.out.println("jerry value:"+cahceBuilder.get("jerry")); System.out.println("peida value:"+cahceBuilder.get("peida")); System.out.println("peida value:"+cahceBuilder.apply("peida")); System.out.println("lisa value:"+cahceBuilder.apply("lisa")); //使用cache.put(key, value)方法能夠直接向緩存中插入值,這會直接覆蓋掉給定鍵以前映射的值 cahceBuilder.put("harry", "ssdded"); System.out.println("harry value:"+cahceBuilder.get("harry")); System.out.println("________________________________________"); List<String> list = new ArrayList<>(); list.add("1"); list.add("2"); System.out.println(cahceBuilder.getAll(list)); } //基於Callable加載 @Test public void testcallableCache()throws Exception{ Cache<String, String> cache = CacheBuilder.newBuilder().maximumSize(1000).build(); String resultVal = cache.get("jerry", new Callable<String>() { public String call() { String strProValue="hello "+"jerry"+"!"; return strProValue; } }); System.out.println("jerry value : " + resultVal); resultVal = cache.get("peida", new Callable<String>() { public String call() { String strProValue="hello "+"peida"+"!"; return strProValue; } }); System.out.println("peida value : " + resultVal); } }
使用CacheBuilder構建的緩存不會"自動"執行清理和回收工做,也不會在某個緩存項過時後立刻清理,也沒有諸如此類的清理機制。相反,它會在寫操做時順帶作少許的維護工做,或者偶爾在讀操做時作——若是寫操做實在太少的話。緩存
這樣作的緣由在於:若是要自動地持續清理緩存,就必須有一個線程,這個線程會和用戶操做競爭共享鎖。此外,某些環境下線程建立可能受限制,這樣CacheBuilder就不可用了。安全
相反,咱們把選擇權交到你手裏。若是你的緩存是高吞吐的,那就無需擔憂緩存的維護和清理等工做。若是你的 緩存只會偶爾有寫操做,而你又不想清理工做阻礙了讀操做,那麼能夠建立本身的維護線程,以固定的時間間隔調用Cache.cleanUp()。ScheduledExecutorService能夠幫助你很好地實現這樣的定時調度。oracle
CacheBuilder.maximumSize(long)。app
//。在權重限定場景中,除了要注意回收也是在重量逼近限定值時就進行了, //還要知道重量是在緩存建立時計算的,所以要考慮重量計算的複雜度。 Cache<String, String> cache = CacheBuilder.newBuilder().maximumSize(1000) .maximumWeight(100) .weigher(new Weigher<String,String>(){ @Override public int weigh(String key, String value) { // TODO Auto-generated method stub return value.getBytes().length; } }).build();
經過使用弱引用的鍵、或弱引用的值、或軟引用的值,Guava Cache能夠把緩存設置爲容許垃圾回收:異步
任什麼時候候,你均可以顯式地清除緩存項,而不是等到它被回收:ide
LoadingCache<String,String> cahceBuilder=CacheBuilder .newBuilder() //注意:緩存並不會由於刷新盲目地定時重置,若是緩存項沒有被檢索,那刷新就不會真的發生, //(能夠理解未異步定時獲取新增,而不會作刷新,只有被檢索時纔會真正刷新) //若是設置過時(expireAfterWrite)緩存項在過時時間後也變得能夠回收。 .refreshAfterWrite(2, TimeUnit.MINUTES) .build(new CacheLoader<String, String>(){ //提供默認的加載加載方式,在實際生產中,能夠選擇從DB中,或者文件中加載相應的value @Override public String load(String key) throws Exception { String strProValue="hello "+key+"!"; return strProValue; } //從新加載:重載CacheLoader.reload(K, V)能夠擴展刷新時的行爲,這個方法容許開發者在計算新值時使用舊的值。 @Override public ListenableFuture<String> reload(String key, String oldValue) throws Exception { // TODO Auto-generated method stub return super.reload(key, oldValue); } });
Cache<String, String> cache = CacheBuilder.newBuilder().maximumSize(1000) .removalListener(new RemovalListener<String,String>(){ @Override public void onRemoval(RemovalNotification<String, String> removalnotification) { // 釋放資源 }})