1. 程式人生 > >使用google guava做記憶體快取

使用google guava做記憶體快取

google guava中有cache包,此包提供記憶體快取功能。記憶體快取需要考慮很多問題,包括併發問題,快取失效機制,記憶體不夠用時快取釋放,快取的命中率,快取的移除等等。 當然這些東西guava都考慮到了。

guava中使用快取需要先宣告一個CacheBuilder物件,並設定快取的相關引數,然後呼叫其build方法獲得一個Cache介面的例項。請看下面的程式碼和註釋,注意在註釋中指定了Cache的各個引數。

publicstaticvoid main(String[] args)throwsExecutionException,InterruptedException{//快取介面這裡是LoadingCache,LoadingCache在快取項不存在時可以自動載入快取
LoadingCache<Integer,Student> studentCache                 //CacheBuilder的建構函式是私有的,只能通過其靜態方法newBuilder()來獲得CacheBuilder的例項=CacheBuilder.newBuilder()//設定併發級別為8,併發級別是指可以同時寫快取的執行緒數.concurrencyLevel(8)//設定寫快取後8秒鐘過期.expireAfterWrite(8,TimeUnit.SECONDS)//設定快取容器的初始容量為10.initialCapacity(10)//設定快取最大容量為100,超過100之後就會按照LRU最近雖少使用演算法來移除快取項
.maximumSize(100)//設定要統計快取的命中率.recordStats()//設定快取的移除通知.removalListener(newRemovalListener<Object,Object>(){@Overridepublicvoid onRemoval(RemovalNotification<Object,Object> notification){System.out.println(notification.getKey()+" was removed, cause is "+ notification.getCause());}})//build方法中可以指定CacheLoader,在快取不存在時通過CacheLoader的實現自動載入快取
.build(newCacheLoader<Integer,Student>(){@OverridepublicStudent load(Integer key)throwsException{System.out.println("load student "+ key);Student student =newStudent();                                 student.setId(key);                                 student.setName("name "+ key);return student;}});for(int i=0;i<20;i++){//從快取中得到資料,由於我們沒有設定過快取,所以需要通過CacheLoader載入快取資料Student student = studentCache.get(1);System.out.println(student);//休眠1秒TimeUnit.SECONDS.sleep(1);}System.out.println("cache stats:");//最後列印快取的命中率等 情況System.out.println(studentCache.stats().toString());}

以上程式的輸出如下:

load student 1Student{id=1, name=name 1}Student{id=1, name=name 1}Student{id=1, name=name 1}Student{id=1, name=name 1}Student{id=1, name=name 1}Student{id=1, name=name 1}Student{id=1, name=name 1}Student{id=1, name=name 1}1 was removed, cause is EXPIRED
load student 1......Student{id=1, name=name 1}Student{id=1, name=name 1}Student{id=1, name=name 1}Student{id=1, name=name 1}
cache stats:CacheStats{hitCount=17, missCount=3, loadSuccessCount=3, loadExceptionCount=0, totalLoadTime=1348802, evictionCount=2}

看看到在20此迴圈中命中次數是17次,未命中3次,這是因為我們設定快取的過期時間是寫入後的8秒,所以20秒內會失效兩次,另外第一次獲取時快取中也是沒有值的,所以才會未命中3次,其他則命中。

guava的記憶體快取非常強大,可以設定各種選項,而且很輕量,使用方便。另外還提供了下面一些方法,來方便各種需要:

  1. ImmutableMap<K, V> getAllPresent(Iterable<?> keys) 一次獲得多個鍵的快取值
  2. putputAll方法向快取中新增一個或者多個快取項
  3. invalidate 和 invalidateAll方法從快取中移除快取項
  4. asMap()方法獲得快取資料的ConcurrentMap<K, V>快照
  5. cleanUp()清空快取
  6. refresh(Key) 重新整理快取,即重新取快取資料,更新快取