Java本地缓存Caffeine的简单使用

 更新时间:2023年12月28日 11:28:08   作者:一个风轻云淡  
这篇文章主要介绍了Java本地缓存Caffeine的简单使用,Caffeine 是基于 JAVA 8 的高性能本地缓存库,并且在 spring5后,spring 官方放弃了 Guava,而使用了性能更优秀的 Caffeine 作为默认缓存组件,需要的朋友可以参考下

Caffeine基本介绍

Caffeine 是基于 JAVA 8 的高性能本地缓存库。并且在 spring5 (springboot 2.x) 后,spring 官方放弃了 Guava,而使用了性能更优秀的 Caffeine 作为默认缓存组件。

Caffeine是在Guava Cache的基础上做一层封装,性能有明显提高,二者同属于内存级本地缓存。

使用Caffeine后无需使用Guava Cache,从并发的角度来讲,Caffeine明显优于Guava,原因是使用了Java 8最新的StampedLock锁技术。

本地缓存与分布式缓存对应,缓存进程和应用进程同属于一个JVM,数据的读、写在一个进程内完成。

本地缓存没有网络开销,访问速度很快。

Caffeine提供灵活的结构来创建缓存,并且有以下特性:

  • 自动加载条目到缓存中,可选异步方式
  • 可以基于大小剔除
  • 可以设置过期时间,时间可以从上次访问或上次写入开始计算
  • 异步刷新
  • keys自动包装在弱引用中
  • values自动包装在弱引用或软引用中
  • 条目剔除通知
  • 缓存访问统计

简单使用

导入pom依赖

<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
    <version>2.6.2</version>
</dependency>

入门案例

        // 构建cache对象
        Cache<String, String> cache = Caffeine.newBuilder().build();
        // 存数据
        cache.put("k1", "v1");
        // 取数据
        String v1 = cache.getIfPresent("k1");
        System.out.println("k1 = " + v1);
        // 取数据,包含两个参数:
        // 参数一:缓存的key
        // 参数二:Lambda表达式,表达式参数就是缓存的key,方法体是查询数据库的逻辑
        // 优先根据key查询JVM缓存,如果未命中,则执行参数二的Lambda表达式
        String defaultkey = cache.get("k2", key -> {
            // 根据key去数据库查询数据
            return "v2";
        });
        System.out.println("k2 = " + defaultkey);

配置案例

public static LoadingCache<Long, User> loadingCache = Caffeine.newBuilder()
    // 初始的缓存空间大小
    .initialCapacity(5)
    // 缓存的最大条数
    .maximumSize(10)
    .expireAfterWrite(4, TimeUnit.SECONDS)
    .expireAfterAccess(10, TimeUnit.SECONDS)
    .refreshAfterWrite(6, TimeUnit.SECONDS)
    .recordStats()
    //设置缓存的移除通知
    .removalListener(new RemovalListener<Long, User>() {
        @Override
        public void onRemoval(@Nullable Long key, @Nullable User user, @NonNull RemovalCause removalCause) {
            System.out.printf("Key: %s ,值:%s was removed!原因 (%s) \n", key, user, removalCause);
        }
    })
    .build(id -> {
        System.out.println("缓存未命中,从数据库加载,用户id:" + id);
        return User.builder().id(id).userName("Lily").age(new Random().nextInt(20)).build();
    });

参数说明:

  • initialCapacity 初始的缓存空间大小
  • maximumSize 缓存的最大条数
  • maximumWeight 缓存的最大权重
  • expireAfterAccess 最后一次写入或访问后,经过固定时间过期
  • expireAfterWrite 最后一次写入后,经过固定时间过期
  • refreshAfterWrite 写入后,经过固定时间过期,下次访问返回旧值并触发刷新
  • weakKeys 打开 key 的弱引用
  • weakValues 打开 value 的弱引用
  • softValues 打开 value 的软引用
  • recordStats 缓存使用统计
  • expireAfterWrite 和 expireAfterAccess 同时存在时,以 expireAfterWrite 为准。
  • weakValues 和 softValues 不可以同时使用。
  • maximumSize 和 maximumWeight 不可以同时使用。

清除策略

Caffeine提供了三种缓存驱逐策略:

基于容量:设置缓存的数量上限

// 创建缓存对象
Cache<String, String> cache = Caffeine.newBuilder()
    .maximumSize(1) // 设置缓存大小上限为 1
    .build();

基于时间:设置缓存的有效时间

// 创建缓存对象
Cache<String, String> cache = Caffeine.newBuilder()
    // 设置缓存有效期为 10 秒,从最后一次写入开始计时 
    .expireAfterWrite(Duration.ofSeconds(10)) 
    .build();

基于引用:设置缓存为软引用或弱引用,利用GC来回收缓存数据。性能较差,不建议使用。

    // 构建cache对象
        Cache<String, String> cache = Caffeine.newBuilder()
                .weakKeys().weakValues().build();

Caffeine.weakKeys() 使用弱引用存储key。如果没有强引用这个key,则GC时允许回收该条目

Caffeine.weakValues() 使用弱引用存储value。如果没有强引用这个value,则GC时允许回收该条目

Caffeine.softValues() 使用软引用存储value, 如果没有强引用这个value,则GC内存不足时允许回收该条目

引用类型被垃圾回收时间用途生存时间
强引用从来不会对象的一般状态JVM停止运行时终止
软引用在内存不足时对象缓存内存不足时终止
弱引用在垃圾回收时对象缓存gc运行后终止
虚引用UnknownUnknownUnknown

GuavaCache和Caffeine差异

剔除算法方面,GuavaCache采用的是「LRU」算法,而Caffeine采用的是「Window TinyLFU」算法,这是两者之间最大,也是根本的区别。

立即失效方面,Guava会把立即失效 (例如:expireAfterAccess(0) and expireAfterWrite(0)) 转成设置最大Size为0。这就会导致剔除提醒的原因是SIZE而不是EXPIRED。Caffiene能正确识别这种剔除原因。

取代提醒方面,Guava只要数据被替换,不管什么原因,都会触发剔除监听器。而Caffiene在取代值和先前值的引用完全一样时不会触发监听器。

异步化方方面,Caffiene的很多工作都是交给线程池去做的(默认:ForkJoinPool.commonPool()),例如:剔除监听器,刷新机制,维护工作等。

到此这篇关于Java本地缓存Caffeine的简单使用的文章就介绍到这了,更多相关Java本地缓存Caffeine内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • idea在plugins中搜不到插件的解决方法

    idea在plugins中搜不到插件的解决方法

    本文主要介绍了idea在plugins中搜不到插件的解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-06-06
  • java实现扑克牌发牌器

    java实现扑克牌发牌器

    这篇文章主要为大家详细介绍了java实现扑克牌发牌器,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-04-04
  • tomcat的keepAlive参数深入探究

    tomcat的keepAlive参数深入探究

    这篇文章主要为大家介绍了tomcat的keepAlive参数深入探究,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-11-11
  • Spring Boot使用模板引擎JSP实例解析

    Spring Boot使用模板引擎JSP实例解析

    这篇文章主要介绍了Spring Boot使用模板引擎JSP实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-10-10
  • 解决Eclipse配置Tomcat出现Cannot create a server using the selected type错误

    解决Eclipse配置Tomcat出现Cannot create a server using the selected

    这篇文章主要介绍了解决Eclipse配置Tomcat出现Cannot create a server using the selected type错误的相关资料,需要的朋友可以参考下
    2017-02-02
  • 使用@RequestBody传对象参数时碰到的坑

    使用@RequestBody传对象参数时碰到的坑

    这篇文章主要介绍了使用@RequestBody传对象参数时碰到的坑,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • 关于mybatis if else if 条件判断SQL片段表达式取值和拼接问题

    关于mybatis if else if 条件判断SQL片段表达式取值和拼接问题

    这篇文章主要介绍了mybatis if else if 条件判断SQL片段表达式取值和拼接,文章通过自己真实使用的例子给大家详细介绍,需要的朋友可以参考下
    2021-09-09
  • Java执行JS脚本工具

    Java执行JS脚本工具

    今天小编就为大家分享一篇关于Java执行JS脚本工具,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-12-12
  • SpringMVC整合kinfe4j及问题解决分析

    SpringMVC整合kinfe4j及问题解决分析

    这篇文章主要为大家介绍了SpringMVC整合kinfe4j及问题解决分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • Spring Boot如何通过CORS处理跨域问题

    Spring Boot如何通过CORS处理跨域问题

    这篇文章主要介绍了Spring Boot如何通过CORS处理跨域问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-04-04

最新评论