Guava Cache 建立
基本上能夠經過兩種方式來建立cache:
cacheLoader
callable callback
經過這兩種方法建立的cache,和一般用map來緩存的作法比,不一樣在於,這兩種方法都實現了一種邏輯——從緩存中取key X的值,若是該值已經緩存過了,則返回緩存中的值,若是沒有緩存過,能夠經過某個方法來獲取這個值。
但不一樣的在於cacheloader的定義比較寬泛,是針對整個cache定義的,能夠認爲是統一的根據key值load value的方法。
而callable的方式較爲靈活,容許你在get的時候指定。
下面是兩種方法的例子:
首先是基於cacheloader的方法 java
@Test public void testCacheBuilder() throws ExecutionException { LoadingCache<String, String> graphs = CacheBuilder.newBuilder() .maximumSize(1000) .build(new CacheLoader<String, String>() { public String load(String key) { // 這裏是key根據實際去取值的方法 return "value"; } }); String resultVal = graphs.get("testKey"); System.out.println(resultVal); }
其次是基於實現callable的方法: 緩存
@Test public void testCallable() throws ExecutionException { // 沒有使用CacheLoader Cache<String, String> cache = CacheBuilder.newBuilder() .maximumSize(1000) .build(); String resultVal = cache.get("testKey", new Callable<String>() { public String call() { // 這裏先根據key實際去取值的方法 return "value"; } }); System.out.println(resultVal); }
Guava Cache 數據的移除
被動移除數據的方式,guava默認提供了三種方式:
基於大小的移除
看字面意思就知道就是按照緩存的大小來移除,若是即將到達指定的大小,那就會把不經常使用的鍵值對從cache中移除。
定義的方式通常爲 CacheBuilder.maximumSize(long),官方還介紹了一種能夠算權重的方法,我的認爲實際使用中不太用到,暫不討論。
就這個經常使用的來看有幾個注意點,
其一,這個size指的是cache中的條目數,不是內存大小或是其餘;
其二,並非徹底到了指定的size系統纔開始移除不經常使用的數據的,而是接近這個size的時候系統就會開始作移除的動做;
其三,若是一個鍵值對已經從緩存中被移除了,你再次請求訪問的時候,若是cachebuild是使用cacheloader方式的,那依然仍是會從cacheloader中再取一次值,若是這樣尚未,就會拋出異常
基於時間的移除
guava提供了兩個基於時間移除的方法
expireAfterAccess(long, TimeUnit) 這個方法是根據某個鍵值對最後一次訪問以後多少時間後移除
expireAfterWrite(long, TimeUnit) 這個方法是根據某個鍵值對被建立或值被替換後多少時間移除
基於引用的移除
這種移除方式主要是基於java的垃圾回收機制,根據鍵或者值的引用關係決定移除,我的對垃圾回收這塊不是很是瞭解,竊覺得不太可靠。。也不經常使用。。因此沒有研究,歡迎補充。
主動移除數據方式
主動移除有三種方法:
單獨移除用 Cache.invalidate(key)
批量移除用 Cache.invalidateAll(keys)
移除全部用 Cache.invalidateAll()
若是須要在移除數據的時候有所動做還能夠定義Removal Listener,可是有點須要注意的是默認Removal Listener中的行爲是和移除動做同步執行的,若是須要改爲異步形式,能夠考慮使用RemovalListeners.asynchronous(RemovalListener, Executor)
Guava Cache 的清空,刷新及統計功能
主要介紹guava cache的清空,刷新和統計的功能。
緩存數據的清空
guava沒有提供自動觸發清空緩存數據的功能,而是提供了一種手工調用的方式,使用者須要經過Cache.cleanUp()的方式來清空緩存。
因此通常能夠有兩種選擇,一種是經過某個請求來觸發清空動做,這種至關於按需清空,另外一種則是經過定時任務,亦成爲調度程序來清空,這種至關於與按時清空
緩存數據的刷新
guava沒有提供相似refreshall的方法刷新緩存中的全部值,而只是提供了 LoadingCache.refresh(K)方法,用於刷新某個鍵值對,這裏有趣的是刷新動做是異步的,也就是在值被完全刷新以前,若是有人取這個key的值,返回的仍是沒有刷新的值。 異步
LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder() .maximumSize(1000) .refreshAfterWrite(1, TimeUnit.MINUTES) .build( new CacheLoader<Key, Graph>() { public Graph load(Key key) { // no checked exception return getGraphFromDatabase(key); } public ListenableFuture<Graph> reload(final Key key, Graph prevGraph) { if (neverNeedsRefresh(key)) { return Futures.immediateFuture(prevGraph); } else { // asynchronous! return ListenableFutureTask.create(new Callable<Graph>() { public Graph call() { return getGraphFromDatabase(key); } }); } } });緩存數據統計