ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

google的Guava Cache的使用(超详细)

2021-06-03 12:02:35  阅读:138  来源: 互联网

标签:缓存 Cache System cache google 移除 println Guava cache2


文章目录

1. 引入依赖

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

2. 常用API

2.1 创建缓存

2.1.1 创建LoadingCache缓存

public class CacheTest {

    /**
     * 当进行查询时,若缓存中无数据,那么使用load方法进行动态加载。
     * 若load(key)方法返回"",那么缓存的value=""。
     */
    private static LoadingCache<String, String> cache1 = CacheBuilder.
            newBuilder().
            maximumSize(2).   //LRU缓存的最大个数
            removalListener((notification) -> System.out.println("移除掉的缓存值" +   //移除缓存的回调方法
            notification.getCause().name() + ":" +
            notification.getKey() + ":" +
            notification.getValue())).
            build(new CacheLoader<String, String>() {
                @Override
                public String load(String key) throws Exception {  //动态加载缓存
                    //从SQL或者NoSql 获取对象
                    if ("a".equals(key)) {
                        return "a-v";
                    }
                    return "";
                }
            });
    public static void main(String[] args) throws Exception {
        cache1();
    }


    private static void cache1() throws ExecutionException {

        System.out.println("a的缓存:" + cache1.get("a"));
        System.out.println("b的缓存:" + cache1.get("b"));

        cache1.put("c", "c");
        System.out.println("c的缓存:" + cache1.get("c"));
    }
}

执行结果:

a的缓存:a-v
b的缓存:
移除掉的缓存值SIZE:a:a-v
c的缓存:c

get("b"),因为cache1中并没有缓存,所以会调用CacheLoader的load方法加载缓存,注意CacheLoader的load方法不能返回null。但是返回""后,缓存存储的值如下图2.1-1所示,也是"’。

图2.1-1.png

2.1.2 创建Cache缓存

@Slf4j
public class CacheTest {
   
    private static Cache<String, String> cache2 = CacheBuilder.newBuilder().
            maximumSize(10).build();



    private static void cache2() throws Exception {


        System.out.println("cache2.getIfPresent(a):" + cache2.getIfPresent("a"));

        System.out.println("cache2.get(a) one:" + cache2.get("a", () -> {
            log.info("开始维护缓存,key:{}", "a");
            return "a-v";
        }));
        System.out.println("cache2.get(a) two:" + cache2.get("a", () -> {
            log.info("开始维护缓存,key:{}", "a");
            return "a-v";
        }));
        cache2.invalidate("a");
        System.out.println("invalidate后cache2.getIfPresent(a):" + cache2.getIfPresent("a"));
        //填充值
        cache2.put("b", "b");
        //删除值

        System.out.println("put后cache2.getIfPresent(b):" + cache2.getIfPresent("b"));
    }
}

执行结果:

cache2.getIfPresent(a):null
10:45:22.869 [main] INFO com.tellme.Test.jdk.CacheTest - 开始维护缓存,key:a
cache2.get(a) one:a-v
cache2.get(a) two:a-v
invalidate后cache2.getIfPresent(a):null
put后cache2.getIfPresent(b):b

Cache缓存,可以看做功能更加强大ConcurrentHashMap缓存。

2.2 创建缓存时的API

2.2.1 基于大小的数据移除

API方法作用
maximumSize最大的缓存条数,当达到最大条数,使用LRU移除。
maximumWeight&&weigher最大缓存“重量”,weigher为每一个缓存设置重量,当达到最大重量,使用LRU移除。

maximumWeight也不是基于对象真正占用内存,而是通过weigher为每一个缓存定义重量实现的。

    private static Cache<String, String> cache = CacheBuilder.newBuilder().
            maximumWeight(6).
            weigher((k, v) -> {
                if ("a".equals(k)) {
                    return 5;
                } else {
                    return 1;
                }
            }).
            build();

例如上述代码:key=“a”时,可能缓存的value占用内存比较大,故可以设置权重为5。其余缓存占用的内存比较小,可以设置权重为1。

注意:maximumWeightweigher需要搭配使用。

2.2.2 基于时间的数据移除

API方法作用
expireAfterAccess根据某个键值对最后一次访问之后多少时间后移除
expireAfterWrite据某个键值对被创建或值被替换后多少时间移除
refreshAfterWrite&&LoadingCacheLoadingCache下缓存写入后异步刷新

详细请见——guavaCache本地缓存失效方案expireAfterWrites和refreshAfterWrites

    private static Cache<String, String> cache = CacheBuilder.newBuilder().
            expireAfterAccess(2, TimeUnit.SECONDS).
            build();

2.2.3 基于引用的回收

引用类型作用
强引用常见普通对象引用,只要还有强引用指向一个对象,GC不能回收
软引用JVM认为内存不足,才会试图回收软引用指向的对象
弱引用一旦发生GC,就会回收弱引用指向的对象
虚引用虚引用不会决定对象的生命周期

JVM那点事-对象的自救计划(对象被设为null会被回收吗?)

guava也可以设置value的引用类型,来实现基于引用的回收。

@Slf4j
public class CacheTest {
    /**
     * 缓存大小
     */
    private static Cache<String, String> cache = CacheBuilder.newBuilder().
            weakValues().
            build();

    private static void cache() throws InterruptedException {
        cache.put("a",  new String("a"));
        //显式GC
        System.gc();
        System.out.println(cache.getIfPresent("a"));
    }
}

执行后果

null
API方法作用
softValues软引用,JVM认为内存不足,才会试图回收软引用指向的对象
weakValues弱引用,一旦发生GC,就会回收弱引用指向的对象

2.2.4 removalListener移除缓存时的监听

@Slf4j
public class CacheTest {
    /**
     * 缓存大小
     */
    private static Cache<String, String> cache = CacheBuilder.newBuilder().
            maximumSize(2).
            removalListener((notification) -> System.out.println("移除掉的缓存值" +   //移除缓存的回调方法
                    notification.getCause().name() + ":" +
                    notification.getKey() + ":" +
                    notification.getValue())).
            build();

    private static void cache() throws InterruptedException {
        cache.put("a", "a");
        cache.put("b", "b");
        cache.put("c", "c");
        System.out.println(cache.getIfPresent("a"));
    }
}

执行结果:

移除掉的缓存值SIZE:a:a
null

但是有点需要注意的是默认Removal Listener中的行为是和移除动作同步执行的,如果需要改成异步形式,可以考虑使用RemovalListeners.asynchronous(RemovalListener, Executor)

2.2.5 recordStats开启统计功能

@Slf4j
public class CacheTest {
    private static Cache<String, String> cache = CacheBuilder.newBuilder().
            maximumSize(2).
            recordStats().
            build();
    private static void cache() throws InterruptedException {
        cache.put("a", "a");
        cache.put("b", "b");
        cache.put("c", "c");
        System.out.println(cache.getIfPresent("b"));
        System.out.println(cache.getIfPresent("b"));
        System.out.println(cache.getIfPresent("c"));
        System.out.println(cache.getIfPresent("a"));

        CacheStats stats = cache.stats();
        System.out.println(JSON.toJSONString(stats));
    }
}

效果图:
image.png

2.3 操作缓存的API

2.3.1 显式移除缓存

API方式作用
invalidate(key)单独移除
invalidateAll(keys)批量移除
invalidateAll()移除所有

2.3.2 维护缓存的API

API方式作用
get()存在返回缓存值,不存在则调用Callable<? extends V> loader方法动态生成缓存值并存入缓存中
getIfPresent()若缓存存在则返回缓存,不存在则返回null
put(K key, V value)填充缓存
asMap()将缓存转换为Map

官方文档

guava Cache官方文档

标签:缓存,Cache,System,cache,google,移除,println,Guava,cache2
来源: https://blog.csdn.net/qq_29595463/article/details/117516508

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有