Guava Cache 學習使用
阿新 • • 發佈:2018-12-29
Guava是什麼?
Guava是一組Java的Google核心庫,包括新的集合型別(例如multimap和multiset),不可變集合,圖形庫,函式型別,記憶體快取以及用於併發,I / O,雜湊,基元的API /實用程式,反射,字串處理等等!
Guava Cache呢?
當然是Guava的核心庫之一,主要是用在資料的快取。它有兩種實現方式:CacheLoader與Callable
其他介紹我就不多說了,網上搜了一下,基本上都是此專案在GitHub上的翻譯,github地址:https://github.com/google/guava/wiki/CachesExplained
1.引用
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0</version>
</dependency>
2.CacheLoader實現快取
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import java.util.concurrent.TimeUnit; /** * Created by XiChuan on 2018-12-11. */ public class TestGoogleCache { //建立Cache static LoadingCache<String, Object> cache = CacheBuilder.newBuilder() .refreshAfterWrite(4, TimeUnit.SECONDS) //設定快取獲取時長,如果key過期,就會在快取中刪除此value .maximumSize(10) //最大快取數量 .build(new CacheLoader<String, Object>() { @Override /** 當本地快取沒有此key的value值時,就會呼叫load方法進行查詢,並新增到快取中 **/ public Object load(String appKey) { return queryFromDB(appKey); } }); /** 資料進行庫進行查詢**/ public static Object queryFromDB(String appKey){ System.out.println("query from db"); return System.currentTimeMillis(); } public static void main(String[] args)throws Exception{ String key = "wechat"; for (int i=0; i<8; i++){ System.out.println("-----------i="+i+"------------------"); System.out.println("從cache獲取的值為:"+cache.get(key)); Thread.sleep(1000); /**每獲取一次睡眠1秒*/ } } }
日誌:
-----------i=0------------------ query from db 從cache獲取的值為:1544687107838 -----------i=1------------------ 從cache獲取的值為:1544687107838 -----------i=2------------------ 從cache獲取的值為:1544687107838 -----------i=3------------------ 從cache獲取的值為:1544687107838 -----------i=4------------------ 從cache獲取的值為:1544687107838 -----------i=5------------------ query from db 從cache獲取的值為:1544687112842 -----------i=6------------------ 從cache獲取的值為:1544687112842 -----------i=7------------------ 從cache獲取的值為:1544687112842 Process finished with exit code 0
我們看日誌可以看出,當第一次再cache中獲取值的時候,key=wechat並沒有value值,Cache會從資料庫中查詢。到第五秒的時候,key=wechat到期,Cache會刪除value,並從資料庫中重新獲取。
3.Callable實現快取
/**
* Created by XiChuan on 2018-12-11.
*/
public class TestGoogleCache {
//建立Cache
static Cache<String,Object> cache =
CacheBuilder.newBuilder()
.maximumSize(10) //設定最大快取數量
.expireAfterWrite(4,TimeUnit.SECONDS) //設定快取過期時間
.build();
/**從快取中獲取值*/
public static Object getValueFromCache(String appKey)throws Exception{
return cache.get(appKey, new Callable<Object>() {
/**當本地快取沒有此key的value值時,就會呼叫load方法進行查詢,並新增到快取中 */
@Override
public Object call() throws Exception {
return queryFromDB(appKey);
}
});
}
/** 資料進行庫進行查詢**/
public static Object queryFromDB(String appKey){
System.out.println("query from db");
return System.currentTimeMillis();
}
public static void main(String[] args)throws Exception{
String key = "wechat";
for (int i=0; i<8; i++){
System.out.println("-----------i="+i+"------------------");
System.out.println("從cache獲取的值為:"+getValueFromCache(key));
Thread.sleep(1000); /**每獲取一次睡眠1秒*/
}
}
}
日誌:
-----------i=0------------------
query from db
從cache獲取的值為:1544687715137
-----------i=1------------------
從cache獲取的值為:1544687715137
-----------i=2------------------
從cache獲取的值為:1544687715137
-----------i=3------------------
從cache獲取的值為:1544687715137
-----------i=4------------------
query from db
從cache獲取的值為:1544687719149
-----------i=5------------------
從cache獲取的值為:1544687719149
-----------i=6------------------
從cache獲取的值為:1544687719149
-----------i=7------------------
從cache獲取的值為:1544687719149
Process finished with exit code 0
可以看出,處理的結果都是一樣的。
4.其他有用的方法
有時候,我們並不想當快取時間過期後才清除快取項,我們可以顯式地將快取清除。
Cache.invalidate(key) //清除一個快取
Cache.invalidateAll(keys) //根據keys批量清除
Cache.invalidateAll() //清除所有快取
5.對Callable實現方式進行封裝
@Configuration
public class CacheConfig {
public final static long CACHE_MAX_SIZE = 20; //最大快取數量
public final static int CACHE_REFRESH = 10; //失效時長
@Bean(name = "access_token")
public Cache<String,Object> accessTokenCache(){
return CacheBuilder.newBuilder()
.maximumSize(CACHE_MAX_SIZE)
.expireAfterWrite(CACHE_REFRESH, TimeUnit.SECONDS)
.build();
}
public static Object getValue(Cache<String,Object> cache, String key, Callable<Object> callable)throws ExecutionException{
return cache.get(key,callable);
}
}
public interface WechatService {
Object getAccessToken()throws Exception;
}
/**
* Created by XiChuan on 2018-12-13.
*/
@Service
public class WechatServiceImpl implements WechatService {
@Autowired
@Qualifier(value = "access_token")
Cache<String,Object> accessTokenCache;
/** 從快取中獲取accessToken */
@Override
public Object getAccessToken() throws Exception{
return CacheConfig.getValue(accessTokenCache,"XICHUAN",() -> getFromApi());
}
/**模擬通過介面獲取accessToken*/
private String getFromApi(){
System.out.println("-----從資料庫中讀取------------");
return "1234567890zxcvbnm";
}
}
此封裝方式是在公司中看到大神封裝的,看完後感覺挺實用的,然後就借鑑過來自己封裝了一下。