美文网首页
google的Guava Cache的使用

google的Guava Cache的使用

作者: 小胖学编程 | 来源:发表于2021-06-07 11:38 被阅读0次
  1. 引入依赖
  2. 常用API
    2.1 创建缓存
    -2.1.1 创建LoadingCache缓存
    -2.1.2 创建Cache缓存
    2.2 创建缓存时的API
    -2.2.1 基于大小的数据移除
    -2.2.2 基于时间的数据移除
    -2.2.3 基于引用的回收
    -2.2.4 removalListener移除缓存时的监听
    -2.2.5 recordStats开启统计功能
    2.3 操作缓存的API
    -2.3.1 显式移除缓存
    -2.3.2 维护缓存的API
    官方文档

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&&LoadingCache LoadingCache下缓存写入后异步刷新

详细请见——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官方文档

相关文章

  • java之guava cache应用

    google的guava cache是一个轻量级进程内缓存框架。 如何使用guava cache a. 引入方便,...

  • google Guava Cache使用

    前言:项目需要缓存实时数据,需要根据时间维度去定期清理缓存中的数据,Guava Cache 就比较适合,是一个轻量...

  • Guava Cache本地缓存使用小结

    原创文章,转载请注明原文章地址,谢谢! Guava Cache介绍 guava cache是google guav...

  • google的Guava Cache的使用

    引入依赖 常用API2.1 创建缓存-2.1.1 创建LoadingCache缓存-2.1.2 创建Cache缓存...

  • 初探guava cache实现

    王二北原创,转载请标明出处:来自王二北 1、简单介绍guava cache guava cache是Google ...

  • Guava Cache用法介绍

    Guava Cache的使用场景 参考1 Guava Cache用法介绍2 分布式系统缓存系列之guava cache

  • 高并发系统技术梳理

    缓存 缓存使用常见问题归纳Guava Cache系列之一Guava Cache系列之二Guava Cache系列之...

  • cache

    guava cache的使用

  • 2.2GuavaCache

    Guava Cache是google提供的java API开发工具包的一块。Guava Cache是一个全内存的本...

  • 2019-03-05 cache

    如何提高缓存命中率 Google Guava Cache详解及使用场景 有关于移动边缘计算(MEC)/Cloud-...

网友评论

      本文标题:google的Guava Cache的使用

      本文链接:https://www.haomeiwen.com/subject/mthzsltx.html