基於guava實現本地緩存


今天一個接口響應超時,然后我優化,用到了本地緩存。

maven 依賴

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

 

LocalCache 本地緩存工具類

package com.itbac.common.cache;

import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;



/**
 * 本地緩存工具
 *
 * <br/>對於一些改動頻率低且調用非常頻繁,可加上本地有效時間短(1分鍾)的二級緩存
 *
 * @author Bac
 *
 * @Date 2020年1月6日 下午12:12:12
 */
public class LocalCache<K,V> {

    /**默認的本地緩存最大數據長度*/
    private static final long Default_Maximum_Size = 5_000;
    /**本地緩存數據長度為1    */
    private static final long Single_Size = 1;

    /**寫入本地緩存后的失效時間秒數*/
    private static final long Max_Expire_After_Write = 1 * 60;


    private Cache<K, Optional<V>> cache;

    private LocalCache(){}

    /**
     * 創建本地緩存對象(創建此對象后,需要用static成員變量進行唯一初始化引用)
     * (默認為一分鍾緩存)
     * @return
     */
    public static <K,V> LocalCache<K,V> create() {
        LocalCache<K,V> local = new LocalCache<K,V> ();

        local.cache =  CacheBuilder.newBuilder()
                .maximumSize(Default_Maximum_Size)
                .expireAfterWrite(Max_Expire_After_Write, TimeUnit.SECONDS)
                .build();
        return local;
    }

    /**
     * 創建本地緩存對象
     * @param expireAfterWrite 寫入緩存后失效的秒數
     * @return
     */
    public static <K,V> LocalCache<K,V> create(long expireAfterWrite) {
        LocalCache<K,V> local = new LocalCache<K,V> ();

        local.cache =  CacheBuilder.newBuilder()
                .maximumSize(Default_Maximum_Size)
                .expireAfterWrite(expireAfterWrite <= 0 ?  Max_Expire_After_Write : expireAfterWrite, TimeUnit.SECONDS)
                .build();
        return local;
    }

    /**
     * 創建只能緩存一個數據元素的本地緩存對象
     * @return
     */
    public static <K,V> LocalCache<K,V> createSingleSize() {
        LocalCache<K,V> local = new LocalCache<K,V> ();

        local.cache =  CacheBuilder.newBuilder()
                .maximumSize(Single_Size)
                .expireAfterWrite(Max_Expire_After_Write, TimeUnit.SECONDS)
                .build();
        return local;
    }



    private Cache<K, Optional<V>> getCache() {
        return this.cache;
    }

    /**
     * 獲取緩存k對應的值,沒有值返回null
     * @param k       緩存key
     * @return
     */
    public Optional<V> get(K k) {
        return getCache().getIfPresent(k);
    }


    /**
     * 獲取緩存key對應的值,若key未在本地緩存中,使用call進行初始化
     * @param k          緩存key
     * @param call    若key未在本地緩存中,使用call進行初始化。
     *                可用Lambada表達式, () ->{ 具體邏輯,return V };
     * @return
     */
    public V get(K k,Supplier<V> call) {
        if (k == null) {
            return null;
        }
        /**
         * 由於Guava的Callable接口中,若采用過期機制,
         * 如果自帶的Callable返回了null,get(xx,CallAble)便會拋出異常: CacheLoader returned null for key
         * 故采用Optional + 額外的Supplier
         */
        Optional<V>  value = get(k);
        //未放置本地緩存數據
        if (value == null) {
            V v =  call.get();
            getCache().put(k, Optional.ofNullable(v));
            return v;
        }
        return value.orElse(null);
    }
}

使用本地緩存

package com.itbac.common.cache;

import java.util.ArrayList;
import java.util.List;


public class SkuQueryService {

    //本地緩存,寫入后20秒失效
    private static final LocalCache<String, List<String>> Cache = LocalCache.create(20);

    public static void main(String[] args) {

        //使用本地緩存
        List<String> list = Cache.get("key", () -> {
            //具體獲取數據的邏輯
            List<String> strings = new ArrayList<>();
            strings.add("假裝有數據");
            return strings;
        });

    }
}

設置緩存后,要等到了時間,緩存才會失效。需要容忍一段時間的數據不一致。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM