1. 程式人生 > >Guava Cache 學習使用

Guava Cache 學習使用

Guava是什麼?

Guava是一組Java的Google核心庫,包括新的集合型別(例如multimap和multiset),不可變集合,圖形庫,函式型別,記憶體快取以及用於併發,I / O,雜湊,基元的API /實用程式,反射,字串處理等等!

Guava Cache呢?

當然是Guava的核心庫之一,主要是用在資料的快取。它有兩種實現方式:CacheLoaderCallable

 

其他介紹我就不多說了,網上搜了一下,基本上都是此專案在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";
    }
}

此封裝方式是在公司中看到大神封裝的,看完後感覺挺實用的,然後就借鑑過來自己封裝了一下。