java实现带过期时间的缓存
private static ScheduledExecutorService swapExpiredPool
= new ScheduledThreadPoolExecutor(10); private ReentrantLock lock = new ReentrantLock(); private ConcurrentHashMap<String, Node> cache = new ConcurrentHashMap<>(1024);
/**
* 让过期时间最小的数据排在队列前,在清除过期数据时
* ,只需查看缓存最近的过期数据,而不用扫描全部缓存
*
* @see Node#compareTo(Node)
* @see SwapExpiredNodeWork#run()
*/
private PriorityQueue<Node> expireQueue = new PriorityQueue<>(1024); public LocalCache() { //使用默认的线程池,每5秒清除一次过期数据
//线程池和调用频率 最好是交给调用者去设置。
swapExpiredPool.scheduleWithFixedDelay(
new SwapExpiredNodeWork(), 5, 5, TimeUnit.SECONDS);
} public Object set(String key, Object value, long ttl) { Assert.isTrue(StringUtils.hasLength(key), "key can't be empty");
Assert.isTrue(ttl > 0, "ttl must greater than 0"); long expireTime = System.currentTimeMillis() + ttl;
Node newNode = new Node(key, value, expireTime);
lock.lock();
try {
Node old = cache.put(key, newNode);
expireQueue.add(newNode);
//如果该key存在数据,还要从过期时间队列删除
if (old != null) {
expireQueue.remove(old);
return old.value;
}
return null;
} finally {
lock.unlock();
} } /**
* 拿到的数据可能是已经过期的数据,可以再次判断一下
* if(n.expireTime<System.currentTimeMillis()){
* return null;
* }
* 也可以直接返回整个节点Node ,交给调用者去取舍
* <p>
* <p>
* 无法判断不存在该key,还是该key存的是一个null值,如果需要区分这两种情况
* 可以定义一个全局标识,标识key不存在
* public static final NOT_EXIST = new Object();
* 返回值时
* return n==null?NOT_EXIST:n.value;
*/
public Object get(String key) {
Node n = cache.get(key);
return n == null ? null : n.value;
} /**
* 删出KEY,并返回该key对应的数据
*/
public Object remove(String key) {
lock.lock();
try {
Node n = cache.remove(key);
if (n == null) {
return null;
} else {
expireQueue.remove(n);
return n.value;
}
} finally {
lock.unlock();
}
} /**
* 删除已经过期的数据
*/
private class SwapExpiredNodeWork implements Runnable { @Override
public void run() { long now = System.currentTimeMillis();
while (true) {
lock.lock();
try {
Node node = expireQueue.peek();
//没有数据了,或者数据都是没有过期的了
if (node == null || node.expireTime > now) {
return;
}
cache.remove(node.key);
expireQueue.poll(); } finally {
lock.unlock();
}
}
}
} private static class Node implements Comparable<Node> {
private String key;
private Object value;
private long expireTime; public Node(String key, Object value, long expireTime) {
this.value = value;
this.key = key;
this.expireTime = expireTime;
} /**
* @see SwapExpiredNodeWork
*/
@Override
public int compareTo(Node o) {
long r = this.expireTime - o.expireTime;
if (r > 0) {
return 1;
}
if (r < 0) {
return -1;
}
return 0;
} }
java实现带过期时间的缓存的更多相关文章
- localstorage实现带过期时间的缓存功能
前言 一般可以使用cookie,localstorage,sessionStorage来实现浏览器端的数据缓存,减少对服务器的请求. 1.cookie数据存放在本地硬盘中,只要在过期时间之前,都是有效 ...
- IIS使用十大原则,(IIS过期时间,IIS缓存设置) 【转载】
1. 自定义错误页虽然自定义错误页很简单,但只有少数管理员有效地利用了它.管理员可以在MMC中将HTTP错误信息映像到服务器上的绝对URL或是某个文件,更为详细的信息可以在这里找到.如果你嫌这太麻烦, ...
- redis 过期时间与缓存
设置过期时间 redis对于存储的键值可以设置过期时间,对于过期了的键值,redis会自动删除. > OK > get price " > expire price (in ...
- Redis -- 过期时间 和 缓存 例子
1.设置 key的生存时间,过期自动删除 exprire key seconds 设置过期时间 秒数 ttl key 查询剩余时间 如果 设置了过期时间.对key进行 set 操作,会清除 ...
- 阿里面试官让我实现一个线程安全并且可以设置过期时间的LRU缓存,我蒙了!
目录 1. LRU 缓存介绍 2. ConcurrentLinkedQueue简单介绍 3. ReadWriteLock简单介绍 4.ScheduledExecutorService 简单介绍 5. ...
- [置顶] 页面缓存,cache,设置缓存过期时间,OutputCache
页面缓存 方法一: protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { //缓存有数据 if (Cach ...
- 利用GUID唯一标识符并设置它的过期时间
项目中遇到一个小问题,就是把服务器创建的GUID发送给客户端,客户端接收后,下次访问时带上这个GUID, 服务端这边就进行验证,并做相应的处理. 问题是:项目中还需要这个GUID带过期时间,那是如何设 ...
- 可以设置过期时间的Java缓存Map
前言 最近项目需求需要一个类似于redis可以设置过期时间的K,V存储方式.项目前期暂时不引进redis,暂时用java内存代替. 解决方案 1. ExpiringMap 功能简介 : 1.可设置Ma ...
- java操作Redis缓存设置过期时间
关于Redis的概念和应用本文就不再详解了,说一下怎么在java应用中设置过期时间. 在应用中我们会需要使用redis设置过期时间,比如单点登录中我们需要随机生成一个token作为key,将用户的信息 ...
随机推荐
- vue学习一
自己根据网上的教程新建了一个vue_tes项目.想自己在里面修改,添加各种内容.新建了几个vue页面,一直想把他们关联起来展示.非常心急,没有仔细去看文档,而且网上的教程都是单页面的.很好理解.自己创 ...
- 一起来学习React-Native之react-navigation基本解析
前言 不久前自己也完整开发了一个React-Native项目,对其中的一些知识存在疑惑,再加上项目时间比较紧张,来不及做系统的学习.现在来回顾自己开发当中存在的疑惑点,和大家分享.第一篇是关于路由 ...
- 为什么ROC曲线不受样本不均衡问题的影响
转自:https://blog.csdn.net/songyunli1111/article/details/82285266 在对分类模型的评价标准中,除了常用的错误率,精确率,召回率和F1度量外, ...
- arcgis python 获得打印机
class ToolValidator: """Class for validating a tool's parameter values and controllin ...
- mac 不限速下载大文件
打开终端后,需要在终端处键入一下代码: 「注意:此处代码不完整, 完整版请 关注微信公众号:「100秒分享」,回复编号「334」获取」 cd ~/Downloads && git cl ...
- Git放弃修改
Stage之前放弃修改 如果做了修改,还没有stage(add),使用 git status 可以查看所有的改动: 修改:modified 删除:deleted 添加:Untracked 想要放弃修改 ...
- 视频软件——ffmpeg
1.官网下载地址:http://ffmpeg.org/download.html ffplay.exe ffplay是用于播放的应用程序. ffplay name.mp4 ffprobe.exe ff ...
- ES6 Syntax and Feature Overview
View on GitHub Note: A commonly accepted practice is to use const except in cases of loops and reass ...
- Win10安装PostgreSQL9.6
首先去 官网 下载PostgreSQL 9.6. 可以看到最新版已经到11了,但是我们这里还是以9.6.10版本为例进行下载. 下载好之后点击进行安装,安装期间的一些参数如下: 默认的安装位置是C:\ ...
- 十六章 综合实例——《跟我学Shiro》
目录贴:跟我学Shiro目录贴 简单的实体关系图 简单数据字典 用户(sys_user) 名称 类型 长度 描述 id bigint 编号 主键 username varchar 100 用户名 pa ...