Java如何设置Map过期时间的的几种方法

一、技术背景

在实际的项目开发中,我们经常会使用到缓存中间件(如redis、MemCache等)来帮助我们提高系统的可用性和健壮性。

但是很多时候如果项目比较简单,就没有必要为了使用缓存而专门引入Redis等等中间件来加重系统的复杂性。那么使用Java本身自己的轻量级的缓存组件就是完美解决方式。

二、技术效果

  1. 实现缓存的常见功能
  2. 热点数据预热
  3. 简单限流
  4. 去重

三、ExpiringMap

3.1 ExpiringMap简介

ExpiringMap具有高性能、低开销、零依赖、线程安全、使用 ConcurrentMap 的实现过期 entries 等优点。
功能包括不限于:

  1. 设置 Map 中的 Entry 在一段时间后自动过期。
  2. 设置 Map 最大容纳值,当到达 Max size 后,再次插入值会导致 Map 中的第一个值过期。
  3. 设置 添加监听事件,在监听到 Entry 过期时调度监听函数。
  4. 设置懒加载,在调用 get() 方法时创建对象。
  5. 允许您了解条目预计何时过期

3.2 ExpiringMap使用

3.2.1 pom.xml 中添加依赖
        <!-- https://mvnrepository.com/artifact/net.jodah/expiringmap --><dependency><groupId>net.jodah</groupId><artifactId>expiringmap</artifactId><version>0.5.10</version></dependency>
3.2.2 代码中使用
    /*** ① maxSize:Map存储的最大值,类似队列,容量固定,当操作map容量超出限制时,最开始的元素就会依次过期,只保留最新的;* ② expiration:过期时间;* ③ expirationListener:过期监听,当条目过期时,将同步调用过期侦听器,并且在侦听器完成之前,*  将阻止对映射的写入操作。还可以在单独的线程池中配置和调用异步过期侦听器,而不会阻塞映射操作;* ④ expirationPolicy:过期策略,包括 ExpirationPolicy.ACCESSED 和 ExpirationPolicy.CREATED 两种;*      1)ExpirationPolicy.ACCESSED :每进行一次访问,过期时间就会自动清零,重新计算;*      2)ExpirationPolicy.CREATED:在过期时间内重新 put 值的话,过期时间会清理,重新计算;* ⑤ variableExpiration:可变过期,条目可以具有单独可变的到期时间和策略:*/public static  ExpiringMap<String, String> map = ExpiringMap.builder().maxSize(1000).expiration(2, TimeUnit.HOURS).variableExpiration().expirationPolicy(ExpirationPolicy.ACCESSED).expirationListener((key, value) -> {System.out.println("SseEmitter已过期,key:"+ key);}).build();
3.2.3 参数说明
 ① maxSize:Map存储的最大值,类似队列,容量固定,当操作map容量超出限制时,最开始的元素就会依次过期,只保留最新的;② expiration:过期时间;③ expirationListener:过期监听,当条目过期时,将同步调用过期侦听器,并且在侦听器完成之前,将阻止对映射的写入操作。还可以在单独的线程池中配置和调用异步过期侦听器,而不会阻塞映射操作;④ expirationPolicy:过期策略,包括 ExpirationPolicy.ACCESSED 和 ExpirationPolicy.CREATED 两种;1)ExpirationPolicy.ACCESSED :每进行一次访问,过期时间就会自动清零,重新计算;2)ExpirationPolicy.CREATED:在过期时间内重新 put 值的话,过期时间会清理,重新计算;⑤ variableExpiration:可变过期,条目可以具有单独可变的到期时间和策略;
3.2.4 其他使用方式
		//为单个条目指定到期策略:map.put("1", "张三", ExpirationPolicy.CREATED);map.put("2", "李四", ExpirationPolicy.ACCESSED);//variableExpiration 可变过期 条目可以具有单独可变的到期时间和策略:map.put("3", "王五", ExpirationPolicy.ACCESSED, 5, TimeUnit.MINUTES);//过期时间和策略也可以即时更改:map.setExpiration("1", 5, TimeUnit.MINUTES);map.setExpirationPolicy("1", ExpirationPolicy.ACCESSED);//动态添加和删除过期侦听器:ExpirationListener<String, String> connectionCloser = (key, value) -> System.out.println(key+":"+value);//添加侦听器map.addExpirationListener(connectionCloser);//移除侦听器map.removeExpirationListener(connectionCloser);//设置懒加载
//        Map<String, String> stringMap = ExpiringMap.builder()
//                .expiration(10, TimeUnit.MINUTES)
//                .entryLoader(address -> address)
//                .build();
//        // 通过 EntryLoader 将值加载到map中
//        String value = stringMap.get("1");
//        System.out.println("value值:"+value);//获取条目的到期时间:单位:毫秒long expiration = map.getExpectedExpiration("1");System.out.println("距离过期时间还有:"+expiration+"毫秒");//重置条目的内部到期计时器:map.resetExpiration("1");//查看设置的过期时间map.getExpiration("1");System.out.println("设置的过期时间:"+map.getExpiration("1"));

测试结果

距离过期时间还有:299999毫秒
设置的过期时间:300000

四、Guava的LoadingCache

4.1 LoadingCache简介

做java的我们都知道Guava是一个编程工具类库,其中包含了很多高质量高性能的工具类和方法。其中,LoadingCache便是一个特别好用的功能,其背后的架构其实就是Guava cache,Guava Cache 是一个全内存的本地缓存实现,它提供了线程安全的实现机制,它可以加载缓存中不存在的数据,本质其实是一个键值对(key-value)的缓存,可以通过key获取到对应的缓存值value。
特点:提供缓存回收机制,监控缓存加载/命中情况,灵活强大的功能,简单易上手的api。

4.2 LoadingCache使用

4.2.1 pom.xml 中添加依赖
<dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>24.1-jre</version>
</dependency>
4.2.2 代码中使用
	public static LoadingCache<Long, User> userCache= CacheBuilder.newBuilder()// 缓存池大小,在缓存数量到达该大小时, 开始回收旧的数据.maximumSize(1000)// 设置时间60s对象没有被读/写访问则对象从内存中删除.expireAfterAccess(60, TimeUnit.SECONDS)// 设置缓存在写入之后 设定时间60s后失效.expireAfterWrite(60, TimeUnit.SECONDS)// 定时刷新,设置时间10s后,当有访问时会重新执行load方法重新加载.refreshAfterWrite(10, TimeUnit.SECONDS)// 移除监听器,缓存项被移除时会触发.removalListener(new RemovalListener() {@Overridepublic void onRemoval(RemovalNotification rn) {// 处理缓存键不存在缓存值时的处理逻辑log.error(rn.getKey() + "remove");}})// 处理缓存键对应的缓存值不存在时的处理逻辑.build(new CacheLoader<Long, User>() {@Overridepublic User load(Long id) {return getById(id);}});public User getUser(Long id) {User user = userCache.get(id);}public ImmutableMap<Long, User > getAll(List<Long> ids) throws ExecutionException {return cache.getAll(ids);}
4.2.3 参数说明
 ① maximumSize:缓存的k-v最大数据,当总缓存的数据量达到这个值时,就会淘汰它认为不太用的一份数据,会使用LRU策略进行回收;② expireAfterAccess:缓存项在给定时间内没有被读/写访问,则回收,这个策略主要是为了淘汰长时间不被访问的数据;③ expireAfterWrite:缓存项在给定时间内没有被写访问(创建或覆盖),则回收, 防止旧数据被缓存过久;④ refreshAfterWrite:缓存项在给定时间内没有被写访问(创建或覆盖),则刷新;⑤ recordStats:开启Cache的状态统计(默认是开启的);
4.2.4 GET方法
  V get(K key, int hash, CacheLoader<? super K, V> loader) throws ExecutionException {try {if (count != 0) { // read-volatileReferenceEntry<K, V> e = getEntry(key, hash);if (e != null) {long now = map.ticker.read();//检查entry是否符合expireAfterAccess淘汰策略V value = getLiveValue(e, now);// value是有效的 则返回if (value != null) {// 记录该值的最近访问时间recordRead(e, now);statsCounter.recordHits(1);// 内部实现了定时刷新,若未开启refreshAfterWrite则直接返回valuereturn scheduleRefresh(e, key, hash, value, now, loader);}ValueReference<K, V> valueReference = e.getValueReference();// 如果有别的线程已经在load value,则等到其他线程完成后再取结果if (valueReference.isLoading()) {return waitForLoadingValue(e, key, valueReference);}}}// 如果没拿到有效的value,则执行加载逻辑;return lockedGetOrLoad(key, hash, loader);} catch (ExecutionException ee) {...} finally {postReadCleanup();}}
4.2.5 Load方法
@GwtCompatible(emulated = true)
public abstract class CacheLoader<K, V> {public abstract V load(K key) throws Exception;}

在这里插入图片描述

4.3 移除机制

guava做cache时候数据的移除分为被动移除和主动移除两种。

  1. 被动移除
  • 基于大小的移除:数量达到指定大小,会把不常用的键值移除
  • 基于时间的移除:expireAfterAccess(long, TimeUnit) 根据某个键值对最后一次访问之后多少时间后移除。expireAfterWrite(long, TimeUnit) 根据某个键值对被创建或值被替换后多少时间移除
  • 基于引用的移除:主要是基于java的垃圾回收机制,根据键或者值的引用关系决定移除
  1. 主动移除
  • 单独移除:Cache.invalidate(key)
  • 批量移除:Cache.invalidateAll(keys)
  • 移除所有:Cache.invalidateAll()

如果配置了移除监听器RemovalListener,则在所有移除的动作时会同步执行该listener下的逻辑。
如需改成异步,使用:RemovalListeners.asynchronous(RemovalListener, Executor)。

4.4 其他

  • 在put操作之前,如果已经有该键值,会先触发removalListener移除监听器,再添加
  • 配置了expireAfterAccess和expireAfterWrite,但在指定时间后没有被移除。
  • 删除策略逻辑:
    CacheBuilder构建的缓存不会在特定时间自动执行清理和回收工作,也不会在某个缓存项过期后马上清理,它不会启动一个线程来进行缓存维护,因为首先线程相对较重,其次某些环境限制线程的创建。

它会在写操作时顺带做少量的维护工作,或者偶尔在读操作时做。当然,也可以创建自己的维护线程,以固定的时间间隔调用Cache.cleanUp()。

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

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

相关文章

oracle开放某些视图给特定用户,查询报视图不存在问题

以sysdba身份登录到Oracle数据库。 创建新用户。例如&#xff0c;创建一个名为new_user的用户&#xff0c;密码为password&#xff1a; CREATE USER new_user IDENTIFIED BY password;为新用户分配表空间和临时表空间。例如&#xff0c;将表空间users和临时表空间temp分配给新…

数据库精选题(七)(综合模拟题二)

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;数据库 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 目录 一、名词解释 1、事务 2、弱实体集 3、正…

chatglm系列知识

一、目录 chatglm 是什么语言模型与transformer decoder 的区别解释prefix LM与Cause LMchatglm&#xff08;prefix LM&#xff09;与decoder-only LM 核心区别glm 架构chatglm 预训练方式chatglm 微调chatglm与chatglm2、chatglm3的区别chatglm 激活函数采用gelu, 为什么chat…

06 - matlab m_map地学绘图工具基础函数 - 绘制海岸线

06 - matlab m_map地学绘图工具基础函数 - 绘制海岸线 0. 引言1. 关于m_coast2. 关于m_gshhs3. 关于m_gshhs_c、m_gshhs_I、m_gshhs_i、m_gshhs_h、m_gshhs_f4. 关于m_shaperead5. 结语 0. 引言 本篇介绍下m_map中添加绘制海岸线的一系列函数及其用法&#xff0c;主要函数包括m…

【HTML03】HTML表单语法笔记,附带案例-作业

文章目录 表单概述一、表单容器&#xff08;form&#xff09;二、控件相关单词获取本次课程作业和案例 表单概述 允许用户输入信息&#xff0c;和提交信息的-收集用户信息。 表单&#xff1a;表单容器表单控件组成。 控件&#xff1a;输入框、单选按钮、多选、下拉框、多行文…

分布式数据库系统MyCat

MyCat简介 MyCat是一个开源的分布式数据库系统&#xff0c;是一个实现了MySQL协议的服务器&#xff0c;前端用户可以把它看作是一个数据库代理&#xff0c;用MySQL客户端工具和命令行访问&#xff0c;而其后端可以用MySQL原生协议与多个MySQL服务器通信&#xff0c;也可以用JD…

FreeRTOS实时操作系统

1.认识实施操作系统 1.1 裸机和实时操作系统 裸机&#xff1a; 早期嵌入式开发没有嵌入式操作系统的概念&#xff0c;直接操作裸机&#xff0c;在裸机上写程序&#xff0c;比如用51单片机基本就没有操作系统的概念。 通常把程序设计为前后台系统&#xff0c;主要分为两部分&a…

Redis(超详细)

Redis Redis概念&#xff1a; Redis是开源的&#xff0c;遵循BSD的&#xff0c;基于内存数据存储&#xff0c;被用于作为数据库、缓存机制、消息中间件&#xff1b; Redis的特点&#xff1a; 1.高性能key/valu内存xing数据库&#xff1b; 2.支持丰富的数据类型 3.支持持久化&am…

信息系统分析与设计:重点内容|UML在线绘制|数据库技术

目录 UML在线绘图工具信息系统分析与设计第1章 系统思想第2章 信息、管理与信息系统第3章 信息系统建设概论&#x1f31f;第4章 系统规划&#x1f31f;第5章 系统分析概述第6章 流程建模&#x1f31f;业务流程图DFD数据流图&#x1f31f;数据字典 第7章 用例建模(用例图)&#…

Docker搭建yolov8并训练、验证、推理化学仪器数据集

目录 1、安装docker 2、创建yolov8镜像 3、下载代码包 4、下载模型预训练权重 5、制作数据集 6、训练、验证及推理 &#xff08;1&#xff09;训练 &#xff08;2&#xff09;验证 &#xff08;3&#xff09;推理 中文标签显示问题 本文通过docker的方式搭建yolov8运…

OnlyOffice:现代办公的最佳选择

目录 安装 使用 评价 对比&#xff08;与WPS&#xff09; 总结 在当今的数字化办公时代&#xff0c;选择一款功能全面且易于使用的办公软件至关重要。OnlyOffice作为一款现代化的办公软件&#xff0c;凭借其强大的功能和友好的用户体验&#xff0c;逐渐成为了众多企业和个…

无线麦克风哪个品牌音质最好,一文告诉你无线领夹麦克风怎么挑选

随着直播带货和个人视频日志&#xff08;Vlog&#xff09;文化的兴起&#xff0c;以及自媒体内容创作的蓬勃发展&#xff0c;我们见证了麦克风行业的迅猛发展。在这一浪潮中&#xff0c;无线领夹麦克风以其无与伦比的便携性和操作效率&#xff0c;迅速赢得了广大视频制作者的喜…

前端HTML/CSS知识点系列

1. 什么是块级格式化上下文&#xff1f;【BFC(Block formatting context)】 BFC&#xff08;Block FormattingContext&#xff0c;块级格式化上下文&#xff09;是一个独立的渲染区域&#xff0c;其中的元素的布局不会受到外部元素的影响&#xff0c;反之亦然。BFC的创建有助于…

docker环境部署ruoyi系统前后端分离项目

创建局域网 docker network create net-ry 安装Redis 1 安装 创建两个目录 mkdir -p /data/redis/{conf,data} 上传redis.conf文件到/data/redis/conf文件夹中 cd /data/redis/conf 3.2 配置redis.conf文件 配置redis.conf文件&#xff1a; redis.conf文件配置注意&…

轻松两步,借助向量数据库 VectorDB 与千帆 Appbuilder 构建个性化本地问答知识库

在我们日常的工作和生活中&#xff0c;经常会遇到需要快速获取和管理大量信息的情况。无论是解答客户的问题&#xff0c;还是整理公司内部的资料&#xff0c;一个高效的知识库系统都能帮我们省下大量时间和精力。 为了帮助大家快速构建 RAG 应用&#xff0c;我们之前发布了一个…

虚拟机中VSCode+gcc环境配置

一、安装VSCode 1、在官网下载软件包&#xff1a; 地址&#xff1a;Documentation for Visual Studio Code 2、下载后在放置deb包的文件夹直接打开终端&#xff0c;然后输入sudo dpkg -i code_1.90.2-1718751586_amd64.deb 3、安装成功提示&#xff0c;并显示该图标 二、配…

nginx+keepalived+tomcat集群实验

如遇星河 | nginx+keepalived高可用集群实验 木子87 | Keepalived+Nginx+Tomcat 实现高可用Web集群 环境 192.168.40.204 tomcat-1 192.168.40.138 tomcat-2 安装tomcat [root@bogon local]# vim /etc/profile 添加环境变量 JAVA_HOME=/usr/local/java PATH=$J…

mac 常用工具命令集合

一、vim 快捷键 1、移动光标 h j k l 左 下 上 右 箭头上 上移一行 箭头下 下移一行 0 跳至行首&#xff0c;不管有无缩进&#xff0c;就是跳到第0个字符 ^ 跳至行首的第一个字符 $ 跳至行尾 gg 跳至文首 G 调至文尾 5gg/5G 调至第5行w 跳到下一个字首&#xff0c;按标点或…

微信小程序学习(十):生命周期

1、应用生命周期 生命周期说明onLaunch监听小程序初始化&#xff0c;全局只会执行 1 次onShow监听小程序启动或切前台onHide监听小程序切后台 &#x1f517;应用生命周期官方文档 App({/*** 当小程序初始化完成时&#xff0c;会触发 onLaunch&#xff08;全局只触发一次&…

固特超声波清洗机怎么样?三大超声波清洗机美的、固特、希亦谁更好?

眼镜是我们日常生活中不可或缺的用具&#xff0c;但随着使用时间的增长&#xff0c;眼镜上的灰尘和污垢也会逐渐积累&#xff0c;传统的清洗方法往往难以彻底清洁。为了解决这一难题&#xff0c;超声波清洗机出现了&#xff01;它利用超声波振动原理&#xff0c;可以轻松、快速…