天天看點

Guava Cache 本地緩存

目錄

一 Guava Cache 是什麼

二 Guava Cache 應用于什麼場景

三 Guava Cache 基本操作

3.1 依賴引入

3.2 get 操作

3.3 put 操作

四 Guava Cache 緩存驅逐政策

4.1 基于緩存數目的驅逐政策

4.2 基于時間的驅逐政策

4.3 基于引用的驅逐政策

4.4 主動驅逐

4.5 監聽驅逐

一 Guava Cache 是什麼

       Guava Cache 來自于 Google 開源的 Guava 類庫的一個元件,是一個實作比較完全的本地緩存。

二 Guava Cache 應用于什麼場景

       從 Guava 官網介紹,下面三種情況下都可以考慮使用 Guava Cache:

       A 你願意花些記憶體來提高速度。

       B 你期待 keys 被多次查詢。

       C 緩存中存儲的資料容量不會超過記憶體容量。

       總結:本地緩存适用于尺寸較小、高頻的讀取操作、變更操作較少的存儲場景。

三 Guava Cache 基本操作

3.1 依賴引入

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>28.0-jre</version>
</dependency>
           

3.2 get 操作

從 CacheLoader 擷取值

LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
	.maximumSize(1000)
	.build(
        new CacheLoader<Key, Graph>() {
            public Graph load(Key key) throws AnyException {
                return createExpensiveGraph(key);
            }
        });
try {
    return graphs.get(key);
} catch (ExecutionException e) {
    throw new OtherException(e.getCause());
}
           

從 Callable 擷取值

Cache<Key, Value> cache = CacheBuilder.newBuilder()
    .maximumSize(1000)
    .build(); // look Ma, no CacheLoader
...
try {
  // If the key wasn't in the "easy to compute" group, we need to
  // do things the hard way.
  cache.get(key, new Callable<Value>() {
    @Override
    public Value call() throws AnyException {
      return doThingsTheHardWay(key);
    }
  });
} catch (ExecutionException e) {
  throw new OtherException(e.getCause());
}
           

3.3 put 操作

cache.put(key, value)
           

四 Guava Cache 緩存驅逐政策

       當緩存的資料大于記憶體的容量時,需要對緩存中的資料進行驅逐,Guava Cache 提供了三種緩存驅逐政策:基于緩存數目的驅逐政策、基于過期時間的驅逐政策、基于引用的驅逐政策。

4.1 基于緩存數目的驅逐政策

LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
       .maximumWeight(100000)
       .weigher(new Weigher<Key, Graph>() {
          public int weigh(Key k, Graph g) {
            return g.vertices().size();
          }
        })
       .build(
           new CacheLoader<Key, Graph>() {
             public Graph load(Key key) { // no checked exception
               return createExpensiveGraph(key);
             }
           });
           

4.2 基于時間的驅逐政策

A 讀取到資料之後一段時間過期

Cache<Object, Object> cache = CacheBuilder
                .newBuilder()
                .expireAfterAccess(long, TimeUnit)
                .build();
           

B 寫入資料之後一段時間過期

Cache<Object, Object> cache = CacheBuilder
                .newBuilder()
                .expireAfterWrite(long, TimeUnit)
                .build();
           

4.3 基于引用的驅逐政策

       Guava 允許垃圾收集 Cache,Cache 中如果存在鍵或值的弱引用或者值的軟引用,都可能被回收。

Cache<Object, Object> cache = CacheBuilder
                .newBuilder()
                .weakKeys()
                .build();
           
Cache<Object, Object> cache = CacheBuilder
                .newBuilder()
                .weakValues()
                .build();
           
Cache<Object, Object> cache = CacheBuilder
                .newBuilder()
                .softValues()
                .build();
           

4.4 主動驅逐

Cache.invalidate(key);
Cache.invalidateAll(keys);
Cache.invalidateAll();
           

4.5 監聽驅逐

CacheLoader<Key, DatabaseConnection> loader = new CacheLoader<Key, DatabaseConnection> () {
  public DatabaseConnection load(Key key) throws Exception {
    return openConnection(key);
  }
};
RemovalListener<Key, DatabaseConnection> removalListener = new RemovalListener<Key, DatabaseConnection>() {
  public void onRemoval(RemovalNotification<Key, DatabaseConnection> removal) {
    DatabaseConnection conn = removal.getValue();
    conn.close(); // tear down properly
  }
};

return CacheBuilder.newBuilder()
  .expireAfterWrite(2, TimeUnit.MINUTES)
  .removalListener(removalListener)
  .build(loader);
           

上述監聽執行都是同步操作,如果想通過異步執行可以使用:

RemovalListeners.asynchronous(RemovalListener, Executor)
           

五 參考文檔

       https://github.com/google/guava/wiki/CachesExplained

繼續閱讀