ExpiringMap使用详解

一、ExpiringMap概述

ExpiringMap项目地址:https://github.com/jhalterman/expiringmap

1、ExpiringMap简介

针对一些小体量的项目,存储的数据量也不是很大(如校验码)的情况下,使用 Redis会增加系统的复杂性和维护难度。

ExpiringMap就是一个轻量的Java缓存方式,它的功能和Redis类似。

ExpiringMap 是一个具有高性能,低开销,零依赖,由线程安全的 ConcurrentMap 实现过期 entries 等优点的 Map。

主要特点包括:过期策略、可变有效期、最大尺寸、侦听器过期、延迟输入加载、过期自省等。

ExpiringMap基本功能包括:

  • 可设置 Map 中的 Entry 在一段时间后自动过期。
  • 可设置 Map 最大容纳值,当到达 Maximum size 后,再次插入值会导致 Map 中的第一个值过期。
  • 可添加监听事件,在监听到 Entry 过期时调度监听函数。
  • 可以设置懒加载,在调用 get() 方法时创建对象。

2、ExpiringMap常用API

  • enum ExpirationPolicy:枚举,确定 ExpiringMap 元素应如何过期,
    • ACCESSED 根据上次访问的时间使它们过期,即从上次访问后开始计时;
    • CREATED 根据条目的创建时间使它们过期,即从创建之后开始计时。
  • enum TimeUnit:枚举,确定时间单位,MILLISECONDS 时间单位毫秒,SECONDS 时间单位秒,MINUTES 时间单位分钟,HOURS 时间单位小时,DAYS 时间单位天
  • interface EntryLoader<K, V>:按需加载,内有 V load(K key) 方法,调用时将 key 的新值加载到即将过期的映射中。
  • interface ExpiringEntryLoader<K, V>:按需加载,并控制每个值的过期时间(即可变过期时间),内有 ExpiringValue load(K key) 方法,调用时将 key 的新值加载到即将过期的映射中。
  • static final class Builder<K, V>:内部类,ExpiringMap 构造器。 默认为 ExpirationPolicy.CREATED,60 个 TimeUnit.SECONDS 到期和 Integer.MAX_VALUE 的 MAXSIZE。
  • static Builder<Object, Object> builder():创建一个 ExpiringMap 构造器,返回 ExpiringMap.Builder。
  • Builder<K, V> expiration(long duration, TimeUnit timeUnit):构造器中的方法,用于设置 Map 的过期时间,返回 ExpiringMap.Builder。- Builder<K, V> maxSize(int maxSize):设置 Map 的最大个数,超过限制仍要添加元素时将最先过期的元素过期。
  • int getMaxSize():获取 Map 的最大个数。
  • Builder<K1, V1> entryLoader(EntryLoader<? super K1, ? super V1> loader):构造器中的方法,可以设置 EntryLoader,EntryLoader 和 ExpiringEntryLoader,不能同时设置。
  • Builder<K1, V1> expiringEntryLoader(ExpiringEntryLoader<? super K1, ? super V1> loader):构造器中的方法,可以设置 ExpiringEntryLoader,EntryLoader 和 ExpiringEntryLoader,不能同时设置。
  • Builder<K, V> expirationPolicy(ExpirationPolicy expirationPolicy):构造器中的方法,用于设置 Map 的过期策略,返回 ExpiringMap.Builder。
  • Builder<K, V> variableExpiration():构造器中的方法,允许 Map 元素具有各自的到期时间,并允许更改到期时间。
  • Builder<K1, V1> expirationListener(ExpirationListener<? super K1, ? super V1> listener):构造器中的方法,配置监听每个 Map 元素过期, 通知传入的 ExpirationListener 执行预定好的操作。
  • void addExpirationListener(ExpirationListener<K, V> listener):给 ExpiringMap 添加过期监听器。
  • void removeExpirationListener(ExpirationListener<K, V> listener):移出 ExpiringMap 的过期监听。
  • long getExpiration(K key):获取指定 key 对应的元素的过期时间,返回毫秒值。
  • long getExpectedExpiration(K key):获取指定 key 预计到期时间,返货毫秒值。
  • ExpirationPolicy getExpirationPolicy(K key):获取指定 key 对应的元素的过期策略。
  • interface ExpirationListener<K, V>:过期监听接口,有一个 void expired(K key, V value) 方法,过期时自动调用。
  • ExpiringMap<K1, V1> build():创建并返回一个 ExpiringMap。

二、使用示例

使用 ExpiringMap之前,需要引入 pom依赖。

<!-- expiringmap依赖 -->
<dependency><groupId>net.jodah</groupId><artifactId>expiringmap</artifactId><version>0.5.11</version>
</dependency>

1、构建时设置过期时间与过期策略

    /*** 初始化一个ExpiringMap(配置过期时间、过期协议等)*/private final static ExpiringMap<String, String> expireCacheMap = ExpiringMap.builder()// 设置最大值,添加第11个entry时,会导致第1个立马过期(即使没到过期时间)。默认 Integer.MAX_VALUE.maxSize(10)// 允许 Map 元素具有各自的到期时间,并允许更改到期时间。.variableExpiration()// 设置过期时间,如果key不设置过期时间,key永久有效。.expiration(10, TimeUnit.SECONDS).asyncExpirationListener((key, value) -> {log.info("expireCacheMap key数据被删除了 -> key={}, value={}", key, value);})//设置 Map 的过期策略.expirationPolicy(ExpirationPolicy.ACCESSED).build();public static void main(String[] args) throws InterruptedException {expireCacheMap.put("token", UUID.randomUUID().toString());// 模拟线程等待TimeUnit.SECONDS.sleep(8);String token = expireCacheMap.get("token");long expiration = expireCacheMap.getExpiration("token");long expectedExpiration = expireCacheMap.getExpectedExpiration("token");log.info("token ===> " + token);log.info("设置的过期时间 ===> " + expiration / 1000);log.info("剩余过期时间 ===> " + expectedExpiration / 1000);// 模拟线程等待TimeUnit.SECONDS.sleep(10);log.info("token ===> " + expireCacheMap.get("token"));TimeUnit.SECONDS.sleep(60);}

说明一下:

  • maxSize:Map存储的最大值,类似队列,容量固定,当操作map容量超出限制时,最开始的元素就会依次过期,只保留最新的;
  • expirationPolicy:过期策略,包括 ExpirationPolicy.ACCESSED 和 ExpirationPolicy.CREATED 两种;
    • 1)ExpirationPolicy.ACCESSED :每进行一次访问,过期时间就会自动清零,重新计算;
    • 2)ExpirationPolicy.CREATED:在过期时间内重新 put 值的话,过期时间会清理,重新计算;默认策略。

在这里插入图片描述

2、单个元素设置过期时间

    /*** 构建后给单个元素设置过期时间*/private final static ExpiringMap<String, String> expireCacheMap2 = ExpiringMap.builder()// 设置最大值,添加第11个entry时,会导致第1个立马过期(即使没到过期时间)。默认 Integer.MAX_VALUE.maxSize(10)// 允许 Map 元素具有各自的到期时间,并允许更改到期时间。.variableExpiration().asyncExpirationListener((key, value) -> {log.info("expireCacheMap2 key数据被删除了 -> key={}, value={}", key, value);})//设置 Map 的过期策略.expirationPolicy(ExpirationPolicy.ACCESSED).build();public static void main(String[] args) throws InterruptedException {expireCacheMap2.put("token", UUID.randomUUID().toString(), ExpirationPolicy.ACCESSED, 30, TimeUnit.SECONDS);expireCacheMap2.put("token2", UUID.randomUUID().toString(), ExpirationPolicy.CREATED, 30, TimeUnit.SECONDS);// 模拟线程等待TimeUnit.SECONDS.sleep(10);log.info("token ===> " + expireCacheMap2.get("token"));log.info("设置的过期时间 ===> " + expireCacheMap2.getExpiration("token") / 1000);log.info("剩余过期时间 ===> " + expireCacheMap2.getExpectedExpiration("token") / 1000);log.info("token2 ===> " + expireCacheMap2.get("token2"));log.info("设置的过期时间 ===> " + expireCacheMap2.getExpiration("token2") / 1000);log.info("剩余过期时间 ===> " + expireCacheMap2.getExpectedExpiration("token2") / 1000);// 模拟线程等待TimeUnit.SECONDS.sleep(20);log.info("token ===> " + expireCacheMap2.get("token"));log.info("token2 ===> " + expireCacheMap2.get("token2"));TimeUnit.SECONDS.sleep(60);}

说明一下:

  • variableExpiration:允许 Map 元素具有各自的到期时间,并允许更改到期时间。也就是说可以设置单个元素的过期时间。

在这里插入图片描述

3、设置懒加载

@Data
public class StudentDTO implements Serializable {private static final long serialVersionUID = 3220190006057051497L;private String name;private Integer age;
}
    /*** 构建后给元素设置懒加载。适合value为引用对象*/private final static ExpiringMap<String, StudentDTO> expireCacheMap3 = ExpiringMap.builder().expiration(10, TimeUnit.SECONDS)//设置懒加载.entryLoader(key -> new StudentDTO()).expirationPolicy(ExpirationPolicy.ACCESSED).build();private final static ExpirationListener<String, StudentDTO> expirationListener = (key, value) -> log.info("expireCacheMap3 key数据被删除了 -> key={}, value={}", key, value);public static void main(String[] args) throws InterruptedException {// 构建时设置过期监听,或者添加过期监听。expireCacheMap3.addExpirationListener(expirationListener);// 使用懒加载时,可以不用去 put 对象,在调用 get 方法时会自动创建对象StudentDTO studentDTO1 = expireCacheMap3.get("studentDTO1");studentDTO1.setName("赵云");studentDTO1.setAge(17);log.info("studentDTO1 ===> " + expireCacheMap3.get("studentDTO1"));TimeUnit.SECONDS.sleep(3);log.info("token ===> " + expireCacheMap3.get("studentDTO1"));log.info("设置的过期时间 ===> " + expireCacheMap3.getExpiration("studentDTO1") / 1000);log.info("剩余过期时间 ===> " + expireCacheMap3.getExpectedExpiration("studentDTO1") / 1000);// 使用懒加载时,可以不用去 put 对象,在调用 get 方法时会自动创建对象StudentDTO studentDTO2 = expireCacheMap3.get("studentDTO2");studentDTO2.setName("赵子龙");studentDTO2.setAge(18);log.info("studentDTO2 ===> " + expireCacheMap3.get("studentDTO2"));TimeUnit.SECONDS.sleep(3);log.info("token ===> " + expireCacheMap3.get("studentDTO2"));log.info("设置的过期时间 ===> " + expireCacheMap3.getExpiration("studentDTO2") / 1000);log.info("剩余过期时间 ===> " + expireCacheMap3.getExpectedExpiration("studentDTO2") / 1000);// 模拟线程等待TimeUnit.SECONDS.sleep(20);log.info("studentDTO1 ===> " + expireCacheMap2.get("studentDTO1"));log.info("studentDTO2 ===> " + expireCacheMap2.get("studentDTO2"));TimeUnit.SECONDS.sleep(60);}

在这里插入图片描述

– 求知若饥,虚心若愚。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/300234.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【论文阅读笔记】Customized Segment Anything Model for Medical Image Segmentation

1.论文介绍 Customized Segment Anything Model for Medical Image Segmentation 医学图像分割的自定义分割模型 2023年 arXiv Paper Code 2.摘要 本文提出SAMed&#xff0c;医学图像分割的一般解决方案。与以往的方法不同&#xff0c;SAMed基于大规模图像分割模型Segment A…

探索数据结构:特殊的双向队列

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;数据结构与算法 贝蒂的主页&#xff1a;Betty’s blog 1. 双向队列的定义 **双向队列(double‑ended queue)**是一种特殊的队列…

【并发编程系列】使用 CompletableFuture 实现并发任务处理

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

python买铅笔 2024年3月青少年电子学会等级考试 中小学生python编程等级考试一级真题答案解析

目录 python买铅笔 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序代码 四、程序说明 五、运行结果 六、考点分析 七、 推荐资料 1、蓝桥杯比赛 2、考级资料 3、其它资料 python买铅笔 2024年3月 python编程等级考试级编程题 一、题目要求 1、编…

Bigtable [OSDI‘06] 论文阅读笔记

原论文&#xff1a;Bigtable: A Distributed Storage System for Structured Data (OSDI’06) 1. Introduction Bigtable 是一种用于管理结构化数据的分布式存储系统&#xff0c;可扩展到非常大的规模&#xff1a;数千台服务器上的数据量可达 PB 级别&#xff0c;同时保证可靠…

《QT实用小工具·十七》密钥生成工具

1、概述 源码放在文章末尾 该项目主要用于生成密钥&#xff0c;下面是demo演示&#xff1a; 项目部分代码如下&#xff1a; #pragma execution_character_set("utf-8")#include "frmmain.h" #include "ui_frmmain.h" #include "qmessag…

js计算器实现

文章目录 1. 演示效果2. 分析思路3. 代码实现 1. 演示效果 2. 分析思路 给每个按钮添加点击事件&#xff0c;使用eval()进行计算。 3. 代码实现 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name&q…

低代码革新:软件开发的未来潜力与创新路径探索

过去的一年&#xff0c;挑战与机遇并存。人们一边忧虑市场经济下行所带来的新的增长难题、裁员危机&#xff0c;一边惊叹于AIGC、量子技术等领域不断涌现新的创新成果。 时代发生了改变&#xff0c;传统“互联网”的模式已走入尾声&#xff0c;新一轮的科技革命与产业变革正在到…

学习 MongoDB:打开强大的数据库技术大门

一、基本概念 MongoDB 是一个基于分布式文件存储的文档数据库&#xff0c;由 C 语言编写。它旨在为 Web 应用提供可扩展的高性能数据存储解决方案。 相信MySQL我们非常的熟悉&#xff0c;那么MySQL的表结构与MongoDB的文档结构进行类比的话可能更好理解MongoDB。 MySQL的数据…

Windows下Docker安装Kafka3+集群

编写 docker-compose.yaml 主要参照&#xff1a;https://www.cnblogs.com/wangguishe/p/17563274.html version: "3"services:kafka1:image: bitnami/kafka:3.4.1container_name: kafka1environment:- KAFKA_HEAP_OPTS-Xmx1024m -Xms1024m- KAFKA_ENABLE_KRAFTyes- K…

类和对象(上)

目录 类的定义&#xff1a; 类的访问限定符及封装&#xff1a; 访问限定符&#xff1a; 封装&#xff1a; 类的作用域&#xff1a; 类的实例化&#xff1a; ​编辑 类对象模型&#xff1a; 类对象的大小与存储方式&#xff1a; this指针&#xff1a; this指针的引出&…

《债务与国家的崛起》西方民主制度的金融起源 - 三余书屋 3ysw.net

债务与国家的崛起&#xff1a;西方民主制度的金融起源 你好&#xff0c;今天我们来聊聊由英国知名经济与金融历史学家詹姆斯麦克唐纳所著的《债务与国家的崛起》这本书。19世纪世界历史上发生了一次巨变&#xff0c;即“大分流”。当时西方通过工业革命实现了科技和经济的飞速…

vue项目入门——index.html和App.vue

vue项目中的index.html文件 在Vue项目中&#xff0c;index.html文件通常作为项目的入口文件&#xff0c;它包含了Vue应用程序的基础结构和配置。 该文件的主要作用是引入Vue框架和其他必要的库&#xff0c;以及定义Vue应用程序的启动配置。 import Vue from vue import App …

以动态库链接库 .dll 探索结构体参数

Dev c C语言实现第一个 dll 动态链接库 创建与调用-CSDN博客 在写dll 插件中发现的函数指针用途和 typedef 的定义指针的用法-CSDN博客 两步之后&#xff0c;尝试加入结构体实现整体数据使用。 注意结构体 Ak 是相同的 代码如下 DLL文件有两个&#xff0c;dll.dll是上面提到…

数据可视化高级技术Echarts(快速上手柱状图进阶操作)

目录 1.Echarts的配置 2.程序的编码 3.柱状图的实现&#xff08;入门实现&#xff09; 相关属性介绍&#xff08;进阶&#xff09;&#xff1a; 1.标记最大值/最小值 2.标记平均值 3.柱的宽度 4. 横向柱状图 5.colorBy series系列&#xff08;需要构造多组数据才能实现…

撸代码时,有哪些习惯一定要坚持?

我从2011年开始做单片机开发&#xff0c;一直保持以下撸代码的习惯。 1.做好代码版本管理 有些人&#xff0c;喜欢一个程序干到底&#xff0c;直到实现全部的产品功能&#xff0c;我以前做51单片机的项目就是这样。 如果功能比较多的产品&#xff0c;我不建议这样做&#xff0…

【Linux】指令

1. 简单指令 whoami 显示当前登入账号名 ls /home 现在有的用户名 adduser 用户名 新加用户&#xff08;必须在root目录下&#xff09; passwd 用户名 给这个用户设置密码 userdel -r 用户名 删除这个用户 pwd 显示当前所处路径 stat 文件名 / 文件夹名 显示文件状…

鸿蒙HarmonyOS 与 Android 的NDK有什么不一样?

1. 序言 就像开发Android要用Android Studio一样&#xff0c;Android Studio&#xff08;简称AS&#xff09;其实是基于IDEAgradle插件android插件开发而来。 鸿蒙系统&#xff0c;你可以认为它和android有点像&#xff0c;但又是超越android的存在&#xff0c;除了手机&…

《C语言深度解剖》(2):详解C语言分支语句和循环

&#x1f921;博客主页&#xff1a;醉竺 &#x1f970;本文专栏&#xff1a;《C语言深度解剖》 &#x1f63b;欢迎关注&#xff1a;感谢大家的点赞评论关注&#xff0c;祝您学有所成&#xff01; ✨✨&#x1f49c;&#x1f49b;想要学习更多数据结构与算法点击专栏链接查看&am…

Java实现二叉树(上)

1.树型结构 1.1树型结构的概念 树是一种 非线性 的数据结构&#xff0c;它是由 n &#xff08; n>0 &#xff09;个有限结点组成一个具有层次关系的集合。 把它叫做树是因为它看 起来像一棵倒挂的树&#xff0c;也就是说它是根朝上&#xff0c;而叶朝下的 1.2树型结构的特点…