Java中的Caffeine加载与驱逐策略详解

 更新时间:2023年10月09日 09:51:53   作者:蜡笔小久  
这篇文章主要介绍了Java中的Caffeine加载与驱逐策略详解,Caffeine是基于Java 8的高性能缓存库,可提供接近最佳的命中率,Caffeine与ConcurrentMap相应,但是不完全相同,本文主要介绍Caffeine,需要的朋友可以参考下

一、Caffiene 简介

Caffeine是基于Java 8的高性能缓存库,可提供接近最佳的命中率。

Caffeine与ConcurrentMap相应,但是不完全相同。最根本的区别是ConcurrentMap会保留所有添加到其中的元素,知道将其明确删除为止. Cache另一方面,通常将A配置为自动删除元素,以限制其内存占用量。在某些情况下,LoadingCache或AsyncLoadingCache可能很有用,即使它没有删除条目, 因为它能够自动加载缓存信息。

二 、Caffeine四种加载策略

1.手动加载缓存信息

Cache<String, Integer> cache = Caffeine.newBuilder()
                // 写入缓存后30分钟后过期
                .expireAfterWrite(30, TimeUnit.MINUTES)
                // 最大缓存数量1000
                .maximumSize(1000)
                .build();
        String key = "1";
        // 新增缓存
        cache.put(key, 1);
        cache.put("2", 2);
        cache.put("3", 3);
        // 从缓存中获取数据: 如果存在在返回"1"的值,如果不存在返回null
        System.out.println(cache.getIfPresent(key));
        // 缓存key不存在cache中, 则新增一条数据到cache中
        String key1 = "4";
        cache.get(key1, k -> 3);
        System.out.println(cache.getIfPresent(key1));
        // 从cache中移除缓存
        cache.invalidate("1");

2.LoadingCache

public void loadingCache() {
    LoadingCache<String, Integer> loadingCache = Caffeine.newBuilder()
            // 写入缓存后30分钟后过期
            .expireAfterWrite(30, TimeUnit.MINUTES)
            // 最大缓存数量1000
            .maximumSize(1000)
            // build中的CacheLoader可以在初始化LoaddingCache时,加载一部分数据到内存中,
            // 此处就把key的hash值作为value
            .build(this::getIntByKey);
    Integer val = loadingCache.get("1", this::getIntByKey);
    System.out.println(val);
	 // 批量获取键值
    Map<String, Integer> all = loadingCache.getAll(Arrays.asList("1", "2"));
    System.out.println(JSON.toJSONString(all.values()));
}
public Integer getIntByKey(String key) {
    return key.hashCode();
}

3.异步手动加载

public void sync() {
        AsyncCache<String, Integer> asyncCache = Caffeine.newBuilder()
        // 写入缓存后30分钟后过期
                .expireAfterWrite(30, TimeUnit.MINUTES)
                // 最大缓存数量1000
                .maximumSize(1000)
            .buildAsync();
        // 如果Key不存在, 则把key和value 加入到cache中, CompletableFuture提供了一个阻塞Cache, 直到异步完成
        CompletableFuture<Integer> future = asyncCache.get("1", this::getIntByKey);
    }
    public Integer getIntByKey(String key) {
        return key.hashCode();
    }

4.异步加载

 public void syncLoadingCache() {
        AsyncLoadingCache<String, Integer> async = Caffeine.newBuilder().buildAsync(new AsyncCacheLoader<>() {
            @Override
            public @NonNull CompletableFuture<Integer> asyncLoad(@NonNull String key, @NonNull Executor executor) {
                return new CompletableFuture<>();
            }
        });
        CompletableFuture<Integer> future = async.get("1");
        CompletableFuture<Map<String, Integer>> all = async.getAll(Arrays.asList("1", "2"));
    }

三、CleanUp

由于Caffeine 不会再值过期后立即执行清除,而是在写入或者读取操作之后执行少量维护工作,或者在写入读取很少的情况下,偶尔执行清除操作。如果我们项目写入或者读取频率很高,那么不用担心。如果想入写入和读取操作频率较低,那么我们可以通过Cache.cleanUp() 加scheduler 去定时执行清除操作。

Scheduler可以迅速删除过期的元素,***Java 9 +***后的版本,可以通过Scheduler.systemScheduler(), 调用系统    线程,达到定期清除的目的

代码实现:

Cache<String, Integer> graphs = Caffeine.newBuilder()
                // 设置一个定时器任务
                .scheduler(Scheduler.systemScheduler())
                // 添加一个移除元素监听事件
                .removalListener((k , v, cause) -> {
                    System.out.println(k);
                    System.out.println(v);
                    System.out.println(cause.wasEvicted());
                })
                .expireAfterWrite(3, TimeUnit.SECONDS)
                .weakValues()
                .build();
        // 创建一个清理线程
        Cleaner cleaner = Cleaner.create();
        // 注册一个对象,并在对象运行时执行一个cleanUp操作
        cleaner.register("1", graphs::cleanUp);
        graphs.put("1", 1);
        graphs.put("2", 2);
        graphs.put("3", 3);
        Thread.sleep(5000);
        graphs.put("3", 3);
        System.out.println(graphs.getIfPresent("1"));
        System.out.println(graphs.getIfPresent("2"));
        System.out.println(graphs.getIfPresent("3"));

到此这篇关于Java中的Caffeine加载与驱逐策略详解的文章就介绍到这了,更多相关Caffeine加载与驱逐策略内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java面向对象编程类的内聚性分析

    java面向对象编程类的内聚性分析

    高内聚、低耦合是软件设计中非常关键的概念。在面向对象程序设计中类的划分时,类的内聚性越高,其封装性越好,越容易复用
    2021-10-10
  • Java如何使用Agent和ASM在字节码层面实现方法拦截

    Java如何使用Agent和ASM在字节码层面实现方法拦截

    Agent是一种运行在 Java 虚拟机 (JVM) 上的特殊程序,ASM是一个轻量级的 Java 字节码编辑和分析框架,本文为大家介绍了如何利用他们在字节码层面实现方法拦截,感兴趣的可以了解一下
    2023-05-05
  • spring cloud Feign使用@RequestLine遇到的坑

    spring cloud Feign使用@RequestLine遇到的坑

    这篇文章主要介绍了spring cloud Feign使用@RequestLine遇到的坑,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • 浅谈java对象的比较

    浅谈java对象的比较

    这篇文章主要给大家分享java对象的比较,主要有元素的比较、类的比较及比较的方法,想具体了解的小伙伴和小编一起进入下面文章内容吧
    2021-10-10
  • ApiOperation和ApiParam注解依赖的安装和使用以及注意事项说明

    ApiOperation和ApiParam注解依赖的安装和使用以及注意事项说明

    这篇文章主要介绍了ApiOperation和ApiParam注解依赖的安装和使用以及注意事项说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-09-09
  • java实现学生成绩档案管理系统

    java实现学生成绩档案管理系统

    这篇文章主要为大家详细介绍了java实现学生成绩档案管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-07-07
  • 一文看懂Mybatis中的延迟加载

    一文看懂Mybatis中的延迟加载

    这篇文章主要介绍了一文看懂Mybatis中的延迟加载,延迟加载也称为懒加载,是指在进行表的关联查询时,按照设置延迟规则推迟对关联对象的select查询,MyBatis 的延迟加载只是对关联对象的查询有迟延设置,对于主加载对象都是直接执行查询语句的,需要的朋友可以参考下
    2023-10-10
  • Java实现给微信群中定时推送消息

    Java实现给微信群中定时推送消息

    这篇文章主要为大家详细介绍了Java如何实现给微信群中定时推送消息的功能,文中的示例代码讲解详细,具有一定的借鉴价值,需要的可以了解一下
    2022-12-12
  • Java集合之LinkedList源码解析

    Java集合之LinkedList源码解析

    这篇文章主要介绍了Java集合之LinkedList源码解析,LinkedList和ArrayList数据结构是完全不一样的,ArrayList 底层是数组的结构,而 LinkedList 的底层则是链表的结构, 它可以进行高效的插入和移除的操作,它基于的是一个双向链表的结构,需要的朋友可以参考下
    2023-12-12
  • JAVA多线程之实现用户任务排队并预估排队时长

    JAVA多线程之实现用户任务排队并预估排队时长

    本文主要介绍了Java多线程之实现用户任务排队并预估排队时长的问题,文中的代码具有一定的学习和工作价值,感兴趣的小伙伴快跟随小编一起学习一下吧
    2021-12-12

最新评论