1. 程式人生 > >Guava Cache 工具類 [ GuavaCacheUtil ]

Guava Cache 工具類 [ GuavaCacheUtil ]


pom.xml


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


GuavaCacheUtil.java


package com.app.core.util;

import com.google.common.cache.*;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.ObjectUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;

@Log4j2
public class GuavaCacheUtil {
    /**
     * 快取項最大數量
     */
    private static final long GUAVA_CACHE_SIZE = 100000;
    /**
     * 快取時間:分鐘
     */
    private static final long GUAVA_CACHE_TIME = 10;

    /**
     * 快取操作物件
     */
    private static LoadingCache<String, Object> GLOBAL_CACHE = null;

    static {
        try {
            GLOBAL_CACHE = loadCache(new CacheLoader<String, Object>() {
                public Object load(String key) throws Exception {
                    // 該方法主要是處理快取鍵不存在快取值時的處理邏輯
                    if (log.isDebugEnabled())
                        log.debug("Guava Cache快取值不存在,初始化空值,鍵名:{}", key);
                    return ObjectUtils.NULL;
                }
            });
        } catch (Exception e) {
            log.error("初始化Guava Cache出錯", e);
        }
    }

    /**
     * 全域性快取設定
     * <ul>
     * <li>快取項最大數量:100000</li>
     * <li>快取有效時間(分鐘):10</li>
     * </ul>
     *
     * @param cacheLoader
     * @return
     * @throws Exception
     */
    private static <K, V> LoadingCache<K, V> loadCache(CacheLoader<K, V> cacheLoader) throws Exception {
        /*
         * maximumSize 快取池大小,在快取項接近該大小時, Guava開始回收舊的快取項 expireAfterAccess 表示最後一次使用該快取項多長時間後失效 removalListener 移除快取項時執行的邏輯方法 recordStats 開啟Guava Cache的統計功能
         */
        LoadingCache<K, V> cache = CacheBuilder.newBuilder().maximumSize(GUAVA_CACHE_SIZE).expireAfterAccess(GUAVA_CACHE_TIME, TimeUnit.MINUTES)
                .removalListener(new RemovalListener<K, V>() {
                    public void onRemoval(RemovalNotification<K, V> rn) {
                        if (log.isDebugEnabled())
                            log.debug("Guava Cache快取回收成功,鍵:{}, 值:{}", rn.getKey(), rn.getValue());
                    }
                }).recordStats().build(cacheLoader);
        return cache;
    }

    /**
     * 設定快取值
     *
     * @param key
     * @param value
     */
    public static void put(String key, Object value) {
        try {
            GLOBAL_CACHE.put(key, value);
            if (log.isDebugEnabled())
                log.debug("快取命中率:{},新值平均載入時間:{}", getHitRate(), getAverageLoadPenalty());
        } catch (Exception e) {
            log.error("設定快取值出錯", e);
        }
    }

    /**
     * 批量設定快取值
     *
     * @param map
     */
    public static void putAll(Map<? extends String, ? extends Object> map) {
        try {
            GLOBAL_CACHE.putAll(map);
            if (log.isDebugEnabled())
                log.debug("快取命中率:{},新值平均載入時間:{}", getHitRate(), getAverageLoadPenalty());
        } catch (Exception e) {
            log.error("批量設定快取值出錯", e);
        }
    }

    /**
     * 獲取快取值
     * <p>注:如果鍵不存在值,將呼叫CacheLoader的load方法載入新值到該鍵中</p>
     *
     * @param key
     * @return
     */
    public static Object get(String key) {
        Object obj = null;
        try {
            obj = GLOBAL_CACHE.get(key);
            if (log.isDebugEnabled())
                log.debug("快取命中率:{},新值平均載入時間:{}", getHitRate(), getAverageLoadPenalty());
        } catch (Exception e) {
            log.error("獲取快取值出錯", e);
        }
        return obj;
    }

    /**
     * 獲取快取值
     * <p>注:如果鍵不存在值,將直接返回 NULL</p>
     *
     * @param key
     * @return
     */
    public static Object getIfPresent(String key) {
        Object obj = null;
        try {
            obj = GLOBAL_CACHE.getIfPresent(key);
            if (log.isDebugEnabled())
                log.debug("快取命中率:{},新值平均載入時間:{}", getHitRate(), getAverageLoadPenalty());
        } catch (Exception e) {
            log.error("獲取快取值出錯", e);
        }
        return obj;
    }

    /**
     * 移除快取
     *
     * @param key
     */
    public static void remove(String key) {
        try {
            GLOBAL_CACHE.invalidate(key);
            if (log.isDebugEnabled())
                log.debug("快取命中率:{},新值平均載入時間:{}", getHitRate(), getAverageLoadPenalty());
        } catch (Exception e) {
            log.error("移除快取出錯", e);
        }
    }

    /**
     * 批量移除快取
     *
     * @param keys
     */
    public static void removeAll(Iterable<String> keys) {
        try {
            GLOBAL_CACHE.invalidateAll(keys);
            if (log.isDebugEnabled())
                log.debug("快取命中率:{},新值平均載入時間:{}", getHitRate(), getAverageLoadPenalty());
        } catch (Exception e) {
            log.error("批量移除快取出錯", e);
        }
    }

    /**
     * 清空所有快取
     */
    public static void removeAll() {
        try {
            GLOBAL_CACHE.invalidateAll();
            if (log.isDebugEnabled())
                log.debug("快取命中率:{},新值平均載入時間:{}", getHitRate(), getAverageLoadPenalty());
        } catch (Exception e) {
            log.error("清空所有快取出錯", e);
        }
    }

    /**
     * 獲取快取項數量
     *
     * @return
     */
    public static long size() {
        long size = 0;
        try {
            size = GLOBAL_CACHE.size();
            if (log.isDebugEnabled())
                log.debug("快取命中率:{},新值平均載入時間:{}", getHitRate(), getAverageLoadPenalty());
        } catch (Exception e) {
            log.error("獲取快取項數量出錯", e);
        }
        return size;
    }

    /**
     * 獲取所有快取項的鍵
     *
     * @return
     */
    public static List<String> keys() {
        List<String> list = new ArrayList<String>();
        try {
            ConcurrentMap<String, Object> map = GLOBAL_CACHE.asMap();
            for (Map.Entry<String, Object> item : map.entrySet())
                list.add(item.getKey());
            if (log.isDebugEnabled())
                log.debug("快取命中率:{},新值平均載入時間:{}", getHitRate(), getAverageLoadPenalty());
        } catch (Exception e) {
            log.error("獲取所有快取項的鍵出錯", e);
        }
        return list;
    }

    /**
     * 快取命中率
     *
     * @return
     */
    public static double getHitRate() {
        return GLOBAL_CACHE.stats().hitRate();
    }

    /**
     * 載入新值的平均時間,單位為納秒
     *
     * @return
     */
    public static double getAverageLoadPenalty() {
        return GLOBAL_CACHE.stats().averageLoadPenalty();
    }

    /**
     * 快取項被回收的總數,不包括顯式清除
     *
     * @return
     */
    public static long getEvictionCount() {
        return GLOBAL_CACHE.stats().evictionCount();
    }
}