Guava Cache工具類及部分參數解析

Guava Cache

最近用到guava的內存緩存,網上找了一些資料,總結了一下,寫了個創建緩存的工具類
只涉及到部分參數,更多可以查看引用資料或者其它文檔

package com.oyo.bizefficiency.workhours.utils;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @Author: Haiyoung
 * @Date: 2019-11-24 20:54
 * @Version 1.0
 */
@Slf4j
public class GuavaCacheUtils {

    /**
     * buildCache
     *
     * expireAfterWrite是在指定項在一定時間內沒有創建/覆蓋時,會移除該key,下次取的時候從loading中取
     * expireAfterAccess是指定項在一定時間內沒有讀寫,會移除該key,下次取的時候從loading中取
     * refreshAfterWrite是在指定時間內沒有被創建/覆蓋,則指定時間過後,再次訪問時,會去刷新該緩存,在新值沒有到來之前,始終返回舊值
     * 跟expire的區別是,指定時間過後,expire是remove該key,下次訪問是同步去獲取返回新值;
     * 而refresh則是指定時間後,不會remove該key,下次訪問會觸發刷新,新值沒有回來時返回舊值
     *
     * 設置的時候,可以讓 expireAfterWrite > refreshAfterWrite, 這樣每間隔refreshAfterWrite時間,當有訪問的時候,進行refresh,
     * 如果超過 expireAfterWrite 沒有訪問,則讓緩存失效, 這樣可以同時利用guava cache的刷新機制和過期機制
     *
     * @param expireAfterWrite
     *            設置寫緩存後過期時間,一個請求進行加載操作,其它請求阻塞
     * @param refreshAfterWrite
     *            設置寫緩存後刷新時間,一個請求進行刷新操作,其它請求返回舊值
     * @param concurrencyLevel
     *            允許同時併發更新操作數。是指對一個緩存中的數據進行更新操作時的併發量。
     *            設置這個參數後,允許併發的最大量不一定會嚴格遵守這個參數。因爲數據被分別存儲到不同的區塊中,而這些數據並不是均勻分佈的。
     *            在代碼實現中,緩存在將會根據這個參數創建對應的ConcurrentMap個數,每一個ConcurrentMap稱爲一個區塊。
     *            數據會分別存儲到每個ConcurrentMap上,還會有另外一個數據結構來維護所有緩存數據所在的位置。
     *            因此,如果將這個參數設置過大,會導致更多時間和空間上的開銷(分配了更多的區塊,需要額外維護這些區塊信息);
     *            如果設置過小,會導致在更新操作時,有大量的線程阻塞(更新同一個ConcurrentMap需要等待鎖)
     * @param initialCapacity
     *            指定用於緩存的hash table最低總規模。——例如設置了initialCapacity爲60,還設置了concurrencyLevel(參閱下文說明)爲8。
     *            將會把存儲的空間分爲8塊,每塊都有一個hash table結構,每個hash table的初始規模爲8。如果緩存空間有限,
     *            需要預估足夠大的初始化空間來緩,避免在數據增長時昂貴的擴展操作(擴展空間會導致深度COPY)
     * @param maximumSize
     *            允許最大的緩存條目數
     * @param cacheLoader
     *            緩存加載邏輯
     * @param <K>
     * @param <V>
     * @return
     */
    public static <K, V> LoadingCache<K, V> buildCache(Integer expireAfterWrite, Integer refreshAfterWrite,
        Integer concurrencyLevel, Integer initialCapacity, Integer maximumSize, CacheLoader<K, V> cacheLoader) {
        LoadingCache<K, V> cache =
            CacheBuilder
                .newBuilder()
                .concurrencyLevel(concurrencyLevel)
                .expireAfterWrite(expireAfterWrite, TimeUnit.SECONDS)
                .refreshAfterWrite(refreshAfterWrite, TimeUnit.SECONDS)
                .initialCapacity(initialCapacity)
                .maximumSize(maximumSize)
                .recordStats()
                .removalListener(
                    notification -> {
                        log.info(notification.getKey() + " was removed,the reason is:"
                                + notification.getCause());
                        System.out.println(notification.getKey() + " was removed,the reason is:"
                                + notification.getCause());
                    }).build(cacheLoader);
        return cache;
    }

    public static void main(String[] args) throws Exception {
        CacheLoader<String, List<String>> cacheLoader = new CacheLoader<String, List<String>>() {
            @Override
            public List<String> load(String key) {
                return loadCache(key);
            }
        };
        LoadingCache<String,List<String>> loadingCache = buildCache(2,1, 1, 32,100, cacheLoader);

        System.out.println(loadingCache.get("1"));
        Thread.sleep(6000);
        System.out.println(loadingCache.get("1"));
    }

    public static List<String> loadCache(String key){
        System.out.println("loadCache begin");
        List<String> list = Lists.newArrayList("AAA", "BBB");
        System.out.println("loadCache end");
        return list;
    }
}

reference

  1. https://juejin.im/post/5d5f6171e51d4561e224a351
  2. https://segmentfault.com/a/1190000015721662
  3. https://my.oschina.net/chkui/blog/726442
  4. https://guava.dev/releases/snapshot-jre/api/docs/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章