前言
最近在做些比较奇葩的项目,架构组要求建设场景时不允许有任何形式的数据存储,一切数据均要存在各支撑组件中,但在实际业务中难免会有需要部分数据需要缓存的情况,如缓存调用第三方API的token信息等,我就在想有没有一种可以支持设定过期时间的map工具,搜索后发现了ExpiringMap。
ExpiringMap
高性能、低开销、线程安全、一款基于内存可过期的 Map,支持自动删除过期的 Key-Value 对, 项目地址戳这里。
主要特点:
- 支持基于时间的键过期。
- 支持基于访问时间的键过期。
- 支持基于Map容纳值大小的键过期。
- 支持添加监听事件,在监听到元素过期时调度监听函数。
- 支持设置懒加载,在调用get()方法时创建对象。
- 线程安全。
- 开源 Apache 2.0。
依赖
<dependency>
<groupId>net.jodah</groupId>
<artifactId>expiringmap</artifactId>
<version>0.5.10</version>
</dependency>
示例
Map容纳值大小的键过期
/**
* description: 构建时设置Map容纳值大小
* date: 2023/12/1 12:40
* author: LenonJin
*/
public static void exMapTest() throws InterruptedException {
// 构建
ExpiringMap<String, Object> exMap = ExpiringMap.builder()
.maxSize(2)
.build();
// 测试
exMap.put("key-1", "第一把钥匙");
exMap.put("key-2", "第二把钥匙");
log.info("exMap-> {}", JSONUtil.toJsonStr(exMap));
exMap.put("key-3", "第三把钥匙");
log.info("exMap-> {}", JSONUtil.toJsonStr(exMap));
}
执行结果
17:13:47.462 [main] INFO com.example.practise.ExMapTest - exMap-> {"key-1":"第一把钥匙","key-2":"第二把钥匙"}
17:13:47.466 [main] INFO com.example.practise.ExMapTest - exMap-> {"key-2":"第二把钥匙","key-3":"第三把钥匙"}
.maxSize: 设置Map的大小,当达到MaxSize后,再次插入会导致Map中的第一个元素过期。
过期时间及过期策略
/**
* description: 构建时设置过期时间及过期策略
* date: 2023/12/1 10:19
* author: LenonJin
*/
public static void exMapTest2() throws InterruptedException {
// 构建
ExpiringMap<String, Object> exMap = ExpiringMap.builder()
.expiration(5, TimeUnit.SECONDS)
.expirationPolicy(ExpirationPolicy.ACCESSED)
.build();
// 测试
exMap.put("token", "5277d026-23a9-42da-96d5-a236ec644870");
log.info(Objects.nonNull(exMap.get("token")) ? "过期时间-> " + exMap.getExpectedExpiration("token") + " ms" : "已过期");
Thread.sleep(6000);
log.info(Objects.nonNull(exMap.get("token")) ? "过期时间-> " + exMap.getExpectedExpiration("token") + " ms" : "已过期");
}
执行结果
17:14:35.955 [main] INFO com.example.practise.ExMapTest - 过期时间-> 4999 ms
17:14:41.968 [main] INFO com.example.practise.ExMapTest - 已过期
.expiration: 设置过期时间,时间单位有 秒、分、时、天。
.expirationPolicy: 设置过期策略,共有两种,ExpirationPolicy.CREATED
在put及replace操作时重置过期时间。ExpirationPolicy.ACCESSED
在get操作时重置过期时间。
单个元素过期时间及策略
/**
* description: 构建后给单个元素设置过期时间及过期策略
* date: 2023/12/1 12:19
* author: LenonJin
*/
public static void exMapTest3() throws InterruptedException {
// 构建
ExpiringMap<String, Object> exMap = ExpiringMap.builder()
.expiration(5, TimeUnit.SECONDS)
.expirationPolicy(ExpirationPolicy.ACCESSED)
.variableExpiration()
.build();
// 测试
exMap.put("token", "5277d026-23a9-42da-96d5-a236ec644870", ExpirationPolicy.CREATED, 10, TimeUnit.SECONDS);
log.info(Objects.nonNull(exMap.get("token")) ? "过期时间-> " + exMap.getExpectedExpiration("token") + " ms" : "已过期");
Thread.sleep(6000);
log.info(Objects.nonNull(exMap.get("token")) ? "过期时间-> " + exMap.getExpectedExpiration("token") + " ms" : "已过期");
}
执行结果
17:16:05.370 [main] INFO com.example.practise.ExMapTest - 过期时间-> 9996 ms
17:16:11.387 [main] INFO com.example.practise.ExMapTest - 过期时间-> 3978 ms
.variableExpiration() 设置Map允许单个元素有各自的到期时间及过期策略。
过期监听
/**
* description: 构建时设置过期监听
* date: 2023/12/1 12:54
* author: LenonJin
*/
public static void exMapTest4() throws InterruptedException {
// 构建
ExpiringMap<String, Object> exMap = ExpiringMap.builder()
.expiration(5, TimeUnit.SECONDS)
.expirationPolicy(ExpirationPolicy.ACCESSED)
.expirationListener((key, value) -> {
log.info("监听到token过期->{}", value);
})
.build();
// 测试
exMap.put("token", "5277d026-23a9-42da-96d5-a236ec644870");
log.info(Objects.nonNull(exMap.get("token")) ? "过期时间-> " + exMap.getExpectedExpiration("token") + " ms" : "已过期");
Thread.sleep(6000);
log.info(Objects.nonNull(exMap.get("token")) ? "过期时间-> " + exMap.getExpectedExpiration("token") + " ms" : "已过期");
}
执行结果
17:16:57.749 [main] INFO com.example.practise.ExMapTest - 过期时间-> 4999 ms
17:17:02.749 [ExpiringMap-Expirer] INFO com.example.practise.ExMapTest - 监听到token过期->5277d026-23a9-42da-96d5-a236ec644870
17:17:03.760 [main] INFO com.example.practise.ExMapTest - 已过期
.expirationListener() 设置监听Map中的每个元素,当元素过期时执行预定操作。
懒加载
/**
* description: 构建时设置懒加载
* date: 2023/12/1 13:54
* author: LenonJin
*/
public static void exMapTest5() throws InterruptedException {
// 构建
ExpiringMap<String, JSONObject> exMap = ExpiringMap.builder()
.expiration(5, TimeUnit.SECONDS)
.expirationPolicy(ExpirationPolicy.ACCESSED)
.entryLoader(key -> new JSONObject())
.build();
// 测试
log.info("exMap-> {}", JSONUtil.toJsonStr(exMap));
JSONObject objA = exMap.get("key-1");
objA.set("name", "第一次GET");
log.info("exMap-> {}", JSONUtil.toJsonStr(exMap));
JSONObject objB = exMap.get("key-2");
objB.set("name", "第二次GET");
log.info("exMap-> {}", JSONUtil.toJsonStr(exMap));
}
执行结果
17:18:11.845 [main] INFO com.example.practise.ExMapTest - exMap-> {}
17:18:11.878 [main] INFO com.example.practise.ExMapTest - exMap-> {"key-1":{"name":"第一次GET"}}
17:18:11.879 [main] INFO com.example.practise.ExMapTest - exMap-> {"key-1":{"name":"第一次GET"},"key-2":{"name":"第二次GET"}}
.entryLoader() 设置Map懒加载,使用时不需再先进行put操作,直接get时会自动创建对象。
想想你的文章写的特别好https://www.237fa.com/
不错不错,我喜欢看 www.jiwenlaw.com
真棒!
《二楼传来的歌声》喜剧片高清在线免费观看:https://www.jgz518.com/xingkong/62431.html
《我的双面爱人》剧情片高清在线免费观看:https://www.jgz518.com/xingkong/18245.html
《火速救兵2》韩国剧高清在线免费观看:https://www.jgz518.com/xingkong/26668.html
《二楼传来的歌声》喜剧片高清在线免费观看:https://www.jgz518.com/xingkong/62431.html
《阿卡普高第二季》海外剧高清在线免费观看:https://www.jgz518.com/xingkong/98328.html
《邪恶花园》恐怖片高清在线免费观看:https://www.jgz518.com/xingkong/106217.html
哈哈哈,写的太好了https://www.lawjida.com/