Guava Cacheの使用を学ぶ

10687 ワード

公式ドキュメント:https://github.com/google/guava/wiki/CachesExplained
 
目次
一、guava cache紹介
二、快速入門
2.1、導入依存
2.2、第一例
2.3、ロット操作
三、開拓
3.1、リスナーの除去
3.2、キャッシュの更新
3.3、カスタムリフレッシュの操作
 
 
一、guava cache紹介
一般的なcache(キャッシュ)の場合、memecache、redis、tairなどのミドルウェアのようなjdkのクラスライブラリの中には、ConcurrentMapインタフェースを実装したConcurrentHashMapなどのキャッシュとして使用できるものもあります.
ConcurrentHashMapでは、プログラムにデータをキャッシュできますが、手動で削除しない限り、データはメモリに存在します.
一方、guava cache(LocalCache、ローカルキャッシュ)は、ConcurrentMapを実現するクラスでもあるが、ConcurrentHashMapとの違いは、guava cacheがデータの期限切れや淘汰メカニズムを設定し、一般的なアプリケーションニーズに合致することである.
guava cacheは、ローカルキャッシュです.つまり、彼のデータはマシンメモリに格納されています.このマシンは、redisのようにキャッシュを専門とするマシンではなく、JVMが存在するマシンです.
 
二、快速入門
2.1、導入依存
guava cahceはguavaのサブモジュールである.
guava倉庫住所:https://mvnrepository.com/artifact/com.google.guava/guava


    com.google.guava
    guava
    28.0-jre


  
2.2、第一例
簡単な例を次に示します.
package cn.ganlixin.guava;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import org.junit.Test;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

public class UseCache {

    @Test
    public void testLoadingCache() throws ExecutionException {
        //     (  )
        LoadingCache cache = CacheBuilder.newBuilder()
                //     1     
                .expireAfterWrite(1, TimeUnit.MINUTES)
                //            3 
                .maximumSize(3)
                //   CacheLoader,               ,   CacheLoader load      。
                .build(new CacheLoader() {
                    //           ,  ,  null ,    
                    @Override
                    public String load(String key) throws Exception {
                        System.out.println("key:" + key + "    ,    ....");
                        return key + "-" + key;
                    }
                });

        //     
        cache.put("Java", "spring");
        cache.put("PHP", "swoole");

        //        
        String res1 = cache.get("Java"); // get      ExecutionException  
        // cache.getUnchecked("Java"); //    get  ,    throw  
        System.out.println(res1);
        //   :spring

        //       key Golang    ,      
        String res2 = cache.get("Golang");
        System.out.println(res2);
        // key:Golang    ,    ....
        // Golang-Golang

        // Golang            ,      ,            value
        String res3 = cache.get("Golang");
        System.out.println(res3);
        // Golang-Golang

        //      3    (        ,        ,      )
        cache.put("Node", "KOA");
        System.out.println(cache.get("PHP")); // PHP cache     
        // key:PHP    ,    ....
        // PHP-PHP

        //     ,     ,        ,    null。
        String res4 = cache.getIfPresent("key");
        System.out.println(res4); // null
    }
}  

  
 
2.3、ロット操作
guava cacheは、一括追加、クエリー、パージ操作をサポートします.
package cn.ganlixin.guava;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap;
import org.junit.Test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

public class UseCache {

    @Test
    public void testMultiple() throws ExecutionException {
        //     
        LoadingCache loadingCache = CacheBuilder.newBuilder()
                .maximumSize(2) //         2
                .expireAfterWrite(10, TimeUnit.SECONDS) //     10   
                .build(new CacheLoader() {
                    @Override
                    public String load(String key) throws Exception {
                        System.out.println("key:" + key + "    ,    ....");
                        return key + "-" + key;
                    }
                });

        Map map = new HashMap<>();
        map.put("one", "111111");
        map.put("two", "222222");
        map.put("three", "3333333");
        //     
        loadingCache.putAll(map);

        List keys = new ArrayList<>();
        keys.add("one");
        keys.add("two");
        //     
        ImmutableMap allData = loadingCache.getAll(keys);
        System.out.println(allData);
        // {one=one-one, two=222222}

        //     
        loadingCache.invalidateAll(keys);
        loadingCache.invalidateAll(); //     
    }
}

  
三、開拓
3.1、リスナーの除去
リスナーの削除とは、キャッシュ・アイテムが消去されたときに指定されたペアの操作を実行するバッファ・アイテムをリスニングすることです.
package cn.ganlixin.guava;

import com.google.common.cache.*;
import org.junit.Test;

import java.util.concurrent.TimeUnit;

public class UseCache {

    @Test
    public void testRemoveListender() {

        LoadingCache cache = CacheBuilder.newBuilder()
                .maximumSize(2)
                .expireAfterWrite(1, TimeUnit.MINUTES)
                //   "     ",       ,  onRemoval  
                .removalListener(new RemovalListener() {
                    @Override
                    public void onRemoval(RemovalNotification removalNotification) {
                        Object key = removalNotification.getKey();
                        Object val = removalNotification.getValue();
                        System.out.println("      ,key:" + key + ", val:" + val);

                    }
                })
                //         key ,  load  。
                .build(new CacheLoader() {
                    //  key    ,       
                    @Override
                    public String load(String key) throws Exception {
                        System.out.println("   key:" + key + ",    ...");
                        return key + key;
                    }
                });

        cache.put("one", "111111");
        cache.put("two", "123456");

        //       ,       ,       
        cache.put("three", "2233333");
        //   :      ,key:one, val:111111

        String res = cache.getUnchecked("four");
        System.out.println(res);
        //    
        //    key:four,    ...
        //       ,key:two, val:123456
        // fourfour
    }
}

  
3.2、キャッシュの更新
キャッシュのリフレッシュとは、キャッシュにバッファ・アイテムが書き込まれた後、一定時間(設定されたリフレッシュ間隔)を経て、再びそのキャッシュ・アイテムにアクセスすると、そのキャッシュ・アイテムがリフレッシュされ、そのアイテムのkeyが取り出され、CacheLoaderのloadメソッドが実行され、戻り値が古い値に置き換えられることを意味します.
キャッシュを作成するときに、キャッシュをリフレッシュする時間を設定できます.
package cn.ganlixin.guava;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import org.junit.Test;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

public class UseCache {

    @Test
    public void testRefresh() throws InterruptedException, ExecutionException {
        LoadingCache cache = CacheBuilder.newBuilder()
                .maximumSize(2)
                //        
                .refreshAfterWrite(2, TimeUnit.SECONDS)
                .build(new CacheLoader() {
                    @Override
                    public String load(String key) throws Exception {
                        System.out.println("key:" + key + "    ,    ....");
                        return key + "-" + key;
                    }
                });

        cache.put("one", "11111");
        cache.put("two", "22222");

        //   3 
        Thread.sleep(3000L);

        System.out.println(cache.get("one"));
        //key:one    ,    ....
        //one-one

        System.out.println(cache.get("two"));
        //key:two    ,    ....
        //two-two
    }
}

なお、上記のコードを例にとると、書き込み2秒後にリフレッシュされるように設定するのではなく、書き込み2秒後に再アクセスされた場合にリフレッシュされる.1つのバッファ・エントリが2秒以上書き込まれたが、エントリにアクセスしなかった場合、このエントリはリフレッシュされません.これはMemecacheとRedisの原理と似ている.
  
3.3、キャッシュの更新操作をカスタマイズする
前述の内容では、設定refreshAfterWrite()を使用してデータをどのくらい書き込んだ後、再びアクセスされるとリフレッシュされるかについて説明していますが、実際には、リフレッシュ操作をカスタマイズするにはCacheLoaderのreloadメソッドを書き換えるだけでよいのです.
package cn.ganlixin.guava;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.ListenableFuture;
import org.junit.Test;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

public class UseCache {

    @Test
    public void testReload() throws InterruptedException {
        LoadingCache cache = CacheBuilder.newBuilder()
                .maximumSize(2)
                //        
                .refreshAfterWrite(2, TimeUnit.SECONDS)
                .build(new CacheLoader() {
                    @Override
                    public String load(String key) throws Exception {
                        System.out.println("key:" + key + "    ,    ....");
                        return key + "-" + key;
                    }

                    //      ,     
                    @Override
                    public ListenableFuture reload(String key, String oldValue) throws Exception {
                        System.out.println("     ,key:" + key + ", oldValue:" + oldValue);
                        return super.reload(key, oldValue);
                    }
                });

        cache.put("hello", "world");
        Thread.sleep(3000L);

        System.out.println(cache.getUnchecked("hello"));
        //      ,key:hello, oldValue:world
        // key:hello    ,    ....
        // hello-hello
    }
}