java内存缓存

 我们在项目中会经常使Redis和Memcache,但是简单项目就没必要使用专门的缓存框架来增加系统的复杂性。用Java代码逻辑就能实现内存级别的缓存。

1.定时任务线程池

使用ScheduledExecutorService结合ConcurrentHashMap,如果你使用的是ConcurrentHashMap,你可以结合使用ScheduledExecutorService来定期检查并清理过期的条目。

public class ExpiringMap<K, V> {private final ConcurrentHashMap<K, ExpiringValue> map = new ConcurrentHashMap<>();private final long expirationTime; // 毫秒private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);public ExpiringMap(long expirationTime) {this.expirationTime = expirationTime;// 安排一个任务定期检查并清理过期条目scheduler.scheduleAtFixedRate(this::cleanUp, expirationTime, expirationTime, TimeUnit.MILLISECONDS);}public void put(K key, V value) {map.put(key, new ExpiringValue(value, System.currentTimeMillis() + expirationTime));}private void cleanUp() {long currentTime = System.currentTimeMillis();map.entrySet().removeIf(entry -> entry.getValue().expirationTime < currentTime);}static class ExpiringValue {final V value;final long expirationTime;ExpiringValue(V value, long expirationTime) {this.value = value;this.expirationTime = expirationTime;}}
}

2. java.time.Instant

和方式一类似,使用java.time.Instant来手动管理过期时间,并结合一个后台线程来定期清理。

public class ExpiringMapWithManualCleanup<K, V> {private final Map<K, Entry<V>> map = new ConcurrentHashMap<>(); private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);private final long expirationTime; // 毫秒public ExpiringMapWithManualCleanup(long expirationTime) {this.expirationTime = expirationTime;scheduler.scheduleAtFixedRate(this::cleanUp, expirationTime, expirationTime, TimeUnit.MILLISECONDS);}public void put(K key, V value) {map.put(key, new Entry<>(value, Instant.now().plusMillis(expirationTime)));}private void cleanUp() {Instant now = Instant.now();map.entrySet().removeIf(entry -> entry.getValue().expirationTime.isBefore(now));}static class Entry<V> {final V value;final Instant expirationTime;Entry(V value, Instant expirationTime) {this.value = value;this.expirationTime = expirationTime;}}
}

3. 使用第三方库

 3.1 ExpiringMap使用

引入依赖

        <dependency><groupId>net.jodah</groupId><artifactId>expiringmap</artifactId><version>0.5.10</version></dependency>
    /*** ① 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();

使用

//为单个条目指定到期策略: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"));

3.2 Google的Guava的LoadingCache

引入依赖

<dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>24.1-jre</version>
</dependency>
maximumSize:缓存的k-v最大数据,当总缓存的数据量达到这个值时,就会淘汰它认为不太用的一份数据,会使用LRU策略进行回收;
expireAfterAccess:缓存项在给定时间内没有被读/写访问,则回收,这个策略主要是为了淘汰长时间不被访问的数据;
expireAfterWrite:缓存项在给定时间内没有被写访问(创建或覆盖),则回收, 防止旧数据被缓存过久;
refreshAfterWrite:缓存项在给定时间内没有被写访问(创建或覆盖),则刷新;
recordStats:开启Cache的状态统计(默认是开启的);
removalListener:移除监听器,缓存项被移除时会触发
build:处理缓存键对应的缓存值不存在时的处理逻辑public static LoadingCache<Long, String> userCache= CacheBuilder.newBuilder().maximumSize(1000).expireAfterAccess(60, TimeUnit.SECONDS).expireAfterWrite(60, TimeUnit.SECONDS).refreshAfterWrite(10, TimeUnit.SECONDS).removalListener(new RemovalListener() {@Overridepublic void onRemoval(RemovalNotification rn) {log.error(rn.getKey() + "remove");}}).build(new CacheLoader<Long, String>() {@Overridepublic String load(Long aLong) throws Exception {return "";}});

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

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

相关文章

智能工厂生产监控大屏-vue纯前端静态页面练习

学习前端还是非常有意思的&#xff0c;因为前端真的是可见即所得&#xff0c;可以做出来非常好看漂亮的页面&#xff0c;最近我就在使用前端技术 做一些大屏报表&#xff0c;在制作这些大屏报表过程中&#xff0c;又熟练的练习了自己的学到的相关的前端技术&#xff0c;接下来把…

HTTP 协议详细介绍

目录一、HTTP 的基本概念与历史演进1. 核心定义2. 历史版本演进二、HTTP 的核心工作原理1. 请求-响应模型2. 基于 TCP 的传输&#xff08;HTTP/1.1、HTTP/2&#xff09;三、HTTP 请求结构1. 请求行2. 请求头3. 请求体四、HTTP 响应结构1. 状态行2. 响应头3. 响应体五、HTTP 与 …

正则化:从过拟合到泛化的「平衡艺术」

在机器学习领域&#xff0c;有一个几乎所有从业者都会遇到的「噩梦」&#xff1a;模型在训练集上表现完美&#xff08;损失趋近于0&#xff09;&#xff0c;但在测试集上却大幅「翻车」。这种现象被称为「过拟合」&#xff08;Overfitting&#xff09;&#xff0c;它像一把双刃…

[Python 基础课程]根据描述定义一个 Person 类

人都属于人类这个物种&#xff0c;每一个人都会有姓名和年龄&#xff0c;人都可以介绍自己&#xff0c;随着时间的流逝&#xff0c;人都会增加年龄&#xff0c;每一个人都能获取到自己的物种信息。 我们的抽象过程&#xff1a; 所有的 Person 对象都应该有一个共同的属性来表示…

热门手机机型重启速度对比

以下是2023-2024年市场主流热门手机机型的重启速度对比分析&#xff0c;基于公开测试数据和用户反馈整理&#xff08;数据会因系统版本和测试环境不同存在波动&#xff09;&#xff1a;旗舰机型重启速度排名&#xff08;冷启动&#xff09;排名机型平均重启时间关键配置优化技术…

第454题.四数相加II

第454题.四数相加II 力扣题目链接(opens new window) 给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) &#xff0c;使得 A[i] B[j] C[k] D[l] 0。 为了使问题简单化&#xff0c;所有的 A, B, C, D 具有相同的长度 N&#xff0c;且 0 ≤ N ≤…

力扣top100(day04-05)--堆

本文为力扣TOP100刷题笔记 笔者根据数据结构理论加上最近刷题整理了一套 数据结构理论加常用方法以下为该文章&#xff1a; 力扣外传之数据结构&#xff08;一篇文章搞定数据结构&#xff09; 215. 数组中的第K个最大元素 class Solution {// 快速选择递归函数int quickselect(…

CCS双轴相位偏移光源 让浅凹痕无处遁形

在工业检测中&#xff0c;浅凹痕表面检测对精度和可靠性要求极高&#xff0c;工业光源在此过程中扮演着关键角色&#xff0c;工业光源通过精准的光学设计&#xff08;角度、波长、强度&#xff09;将肉眼不可见的浅凹痕转化为可量化的光学信号&#xff0c;是实现高精度自动化检…

专题三_二分_x 的平方根

一&#xff1a;题目解释&#xff1a;返回x的算数平方根&#xff0c;如果是小数&#xff0c;则舍去小数部分&#xff0c;返回整数即可&#xff01;二&#xff1a;算法①&#xff1a;暴力从1开始求平方&#xff0c;最后要么直接找到一个值的平方为x&#xff0c;要么发现x在两个相…

Python 操作 Redis 的客户端库 redis-py

Python 操作 Redis 的客户端库 redis-py1. Installation2. Connect and test3. Connection Pools4. Redis Commands4.1. set(name, value, exNone, pxNone, nxFalse, xxFalse, keepttlFalse, getFalse, exatNone, pxatNone)4.1.1. setnx(name, value)4.1.2. setex(name, time, …

社区物业HCommunity本地部署手册

HC小区管理系统安装手动版 更多文章参考&#xff1a; http://www.homecommunity.cn/pages/hc/hcH5_cn.html 1.0 说明 很多开发不太喜欢用梓豪安装&#xff0c;希望通过手工自己安装&#xff0c;这个就需要开发人员 有一定的安装软件能力&#xff0c;比如能够自行安装mysql能…

单例模式-使用局部变量懒汉不用加锁

在 C11 及之后&#xff0c;“局部静态变量懒汉”&#xff08;Meyers’ Singleton&#xff09;不需要自己加锁&#xff0c;标准已经帮你做好了线程安全。 Singleton& getInstance() {static Singleton inst; // ← 这一句并发时只会初始化一次return inst; }首次调用时&am…

51单片机-GPIO介绍

本章概述思维导图&#xff1a;51单片机引脚介绍STC89系列51单片机引脚介绍STC89系列51单片机的引脚是单片机与外部电路连接的接口&#xff0c;用于实现电源供电、时钟信号输入、控制信号输出以及数据输入输出等功能。PDIP封装引脚图&#xff1a;1. 电源引脚&#xff1a;VCC&…

CERT/CC警告:新型HTTP/2漏洞“MadeYouReset“恐致全球服务器遭DDoS攻击瘫痪

2025年8月15日CERT/CC&#xff08;计算机应急响应协调中心&#xff09;近日发布漏洞公告&#xff0c;警告多个HTTP/2实现中新发现的缺陷可能被威胁行为者用于发起高效拒绝服务&#xff08;DoS&#xff09;或分布式拒绝服务&#xff08;DDoS&#xff09;攻击。该漏洞被非正式命名…

[Chat-LangChain] 会话图(LangGraph) | 大语言模型(LLM)

第二章&#xff1a;会话图&#xff08;LangGraph&#xff09; 在第一章中&#xff0c;我们学习了前端用户界面——这是聊天机器人的"面孔"&#xff0c;我们在这里输入问题并查看答案。 我们看到了消息如何从聊天窗口传递到聊天机器人的"大脑"。现在&…

Flask错误处理与会话技术详解

flask入门day03 错误处理 1.abort函数&#xff1a;放弃请求并返回错误代码 详细状态码 from flask import Flask,abort,render_template ​ app Flask(__name__) ​ app.route(/) def index():return 我是首页 ​ app.route(/error) def error():abort(404)return 没有找到…

java程序打包成exe,再打成安装包,没有jdk环境下可运行

一、前提条件准备&#xff1a;1、要被打包的程序文件&#xff1a;rest_assistant-1.0-SNAPSHOT.jarapplication.yml2、图标文件tubiao123.ico3、jre4、打包成exe的软件 config.exe4j5、打成安装包的软件 Inno Setup Compiler二、config.exe4j 的 exe打包配置步骤 按照以下图进行…

区块链技术原理(11)-以太坊交易

文章目录什么是交易&#xff1f;交易类型交易生命周期关键概念&#xff1a;Gas 与交易费用交易状态与失败原因总结什么是交易&#xff1f; “交易&#xff08;Transaction&#xff09;” 是从一个账户向另一个账户发送的经过数字签名的指令 。例如&#xff0c;如果 Bob 发送 A…

小兔鲜儿-小程序uni-app(二)

小兔鲜儿-小程序uni-app7.小兔鲜儿 - 用户模块会员中心页(我的)静态结构参考代码会员设置页分包预下载静态结构退出登录会员信息页静态结构获取会员信息渲染会员信息更新会员头像更新表单信息8.小兔鲜儿 - 地址模块准备工作静态结构地址管理页地址表单页动态设置标题新建地址页…

BLE 广播信道与数据信道:冲突避免、信道映射与自适应跳频实现

低功耗蓝牙(BLE)技术凭借低功耗、短距离、低成本的特性,已广泛应用于智能家居、可穿戴设备、工业物联网等领域。在 BLE 协议中,信道管理是保障通信可靠性的核心机制,其中广播信道与数据信道的设计、冲突避免策略、跳频技术更是面试中的高频考点。本文将从基础原理到实战真…