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/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章