延迟阻塞队列DelayQueue

DelayQueue 是一个支持延时获取元素的阻塞队列,

内部采用优先队列 PriorityQueue 存储元素,

同时元素必须实现 Delayed 接口;在创建元素时可以指定多久才可以从队列中获取当前元素,只有在延迟期满时才能从队列中提取元素。

使用场景

  • 缓存系统:当能够从延迟队列DelayQueue中获取到元素时,说明缓存已经过期
  • 定时任务调度:一分钟后发送短信

基于延迟队列,实现一个缓存系统

延迟队列中添加的元素,实现了Delayed接口

public class CacheItem implements Delayed{
private long expireTime; private long currentTime; private String key; public String getKey() {
return key;
} public CacheItem(String key,long expireTime) {
this.key = key;
this.expireTime = expireTime;
this.currentTime = System.currentTimeMillis();
} /**
* 比较方法,用于排序
* 过期时间长的放队尾,时间短的放队首
*/
@Override
public int compareTo(Delayed o) {
if(this.getDelay(TimeUnit.MICROSECONDS) > o.getDelay(TimeUnit.MICROSECONDS))
return 1;
if(this.getDelay(TimeUnit.MICROSECONDS) > o.getDelay(TimeUnit.MICROSECONDS))
return -1;
return 0;
} /**
* 计算剩余的过期时间
* 大于0说明没有过期
*/
@Override
public long getDelay(TimeUnit unit) { return expireTime - unit.MILLISECONDS.toSeconds(System.currentTimeMillis()-currentTime); } }

缓存实现

public class DelayQueueDemo {
static class Cache implements Runnable{
private Map<String,String> itemMap = new HashMap<>(); private DelayQueue<CacheItem> delayQueue = new DelayQueue<>(); private boolean stop = false; // 初始化后就开始检测
public Cache() {
new Thread(this).start();
} public void add(String key,String value,long expireTime) {
CacheItem item = new CacheItem(key,expireTime);
itemMap.put(key, value);
delayQueue.add(item); } public String get(String key) {
return itemMap.get(key);
} public void shutdown() {
stop = true;
} // 开启多线程,检测缓存是否过期
@Override
public void run() {
while(!stop) {
CacheItem item = delayQueue.poll();
if(item != null) {
// 缓存过期
itemMap.remove(item.getKey());
System.out.println("delete expired key:"+item.getKey());
}
}
System.out.println("Cache stop");
}
} public static void main(String[] args) throws Exception{
Cache cache = new Cache();
cache.add("a", "1", 1);
cache.add("b", "2", 2);
cache.add("c", "3", 2);
cache.add("d", "4", 4);
cache.add("e", "5", 6); while(true) {
String a = cache.get("a");
String b = cache.get("b");
String c = cache.get("c");
String d = cache.get("d");
String e = cache.get("e"); if(a == null && b == null && c == null && d == null && e == null) {
break;
}
} TimeUnit.SECONDS.sleep(1);
cache.shutdown();
} }

延迟队列实现原理部分说明

  • 可重入锁 ReentrantLock
  • 优先队列 PriorityQueue

参考连接

DelayQueue延迟队列-实现缓存的更多相关文章

  1. DelayQueue延迟队列原理剖析

    DelayQueue延迟队列原理剖析 介绍 DelayQueue队列是一个延迟队列,DelayQueue中存放的元素必须实现Delayed接口的元素,实现接口后相当于是每个元素都有个过期时间,当队列进 ...

  2. 延迟队列DelayQueue

    应用场景:有一批广告需要不定时上下架,有可能上下架的时间间隔很长,就没必要用定时器轮询,用延迟队列进行任务执行. public class Test2 { public static void mai ...

  3. 延迟队列DelayQueue take() 源码分析

    延迟队列DelayQueue take() 源码分析 在工作中使用了延迟队列,对其内部的实现很好奇,于是就研究了一下其运行原理,在这里就介绍一下take()方法的源码 1 take()源码 如下所示 ...

  4. JUC——延迟队列

    所谓的延迟队列最大的特征是它可以自动通过队列进行脱离,例如:现在有一些对象被临时保存着,但是有可能该集合对象是一个公共对象,那么里面的某些数据如果不在使用的时候就希望其可以在指定的时间达到后自动的消失 ...

  5. java延迟队列

    大多数用到定时执行的功能都是用任务调度来做的,单身当碰到类似订餐业务/购物等这种业务就不好处理了,比如购物的订单功能,在你的订单管理中有N个订单,当订单超过十分钟未支付的时候自动释放购物车中的商品,订 ...

  6. 灵感来袭,基于Redis的分布式延迟队列

    延迟队列 延迟队列,也就是一定时间之后将消息体放入队列,然后消费者才能正常消费.比如1分钟之后发送短信,发送邮件,检测数据状态等. Redisson Delayed Queue 如果你项目中使用了re ...

  7. RabbitMQ使用 prefetch_count优化队列的消费,使用死信队列和延迟队列实现消息的定时重试,golang版本

    RabbitMQ 的优化 channel prefetch Count 死信队列 什么是死信队列 使用场景 代码实现 延迟队列 什么是延迟队列 使用场景 实现延迟队列的方式 Queue TTL Mes ...

  8. 10 DelayQueue 延时队列类——Live555源码阅读(一)基本组件类

    这是Live555源码阅读的第一部分,包括了时间类,延时队列类,处理程序描述类,哈希表类这四个大类. 本文由乌合之众 lym瞎编,欢迎转载 www.cnblogs.com/oloroso/ 本文由乌合 ...

  9. Java 延迟队列使用

    延时队列,第一他是个队列,所以具有对列功能第二就是延时,这就是延时对列,功能也就是将任务放在该延时对列中,只有到了延时时刻才能从该延时对列中获取任务否则获取不到…… 应用场景比较多,比如延时1分钟发短 ...

随机推荐

  1. SQLAlchemy(十)

    ORM操作在实际项目中的应用非常多,涉及到的框架也是根据不同的项目有不同的处理模块,不过操作流程和步骤都是大同小异基本没有什么太大变化,唯一需要注意的就是在实际操作过程中你要使用的ORM框架的处理性能 ...

  2. mysql数据库读写分离教程

    注意:实现MySQL读写分离的前提是我们已经将MySQL主从复制配置完毕    一.Mycat实现读写分离安装和配置 架构规划: 192.168.201.150 master 主节点 192.168. ...

  3. a href 鼠标滑过变成小手图标

    <a id="l05" style="cursor:pointer;text-decoration:none;" href="<%=pat ...

  4. Centos 修改环境变量

    环境变量文件路径 添加一个X变量,在etc/profile 尾部添加 X=12345即可 输入命令 vim /etc/profile 变量生效 source /etc/profile 测试结果

  5. CSS命名规范整理

    基于网易NEC修改后,整理的命名规范 单行写完一个选择器定义 便于选择器的寻找和阅读,也便于插入新选择器和编辑,便于模块等的识别.去除多余空格,使代码紧凑减少换行. 如果有嵌套定义,可以采取内部单行的 ...

  6. 曼孚科技:“四管齐下”筑牢AI数据隐私安全防线

    谈及数据,绕不开的一个话题就是数据隐私与数据安全.随着数字化进程加快,数据安全事件频发,据Risk Based Security统计,去年国际数据泄露事件近5000起,被泄露数据近41亿条,数据造成的 ...

  7. linux简单命令汇总

    ls [选项] [文件或目录] -a 显示所有文件,包括隐藏文件 -l 显示详细信息 -d 查看目录属性 -h 人性化显示文件大小 -i 显示inode mkdir [选项] 目录名 -p 递归创建 ...

  8. SSM框架——thymeleaf学习总结

    本人关于thymeleaf的学习源自: https://www.bilibili.com/video/BV1qy4y117qi 1.thymeleaf的项目搭建 首先创建springboot项目,相关 ...

  9. codeblocks中报错:'to_string' was not declared in this scope解决方案

    在windows下使用codeblocks(编译器采用MinGW)时,有时会遇到"'to_string' was not declared in this scope"的错误,这里 ...

  10. 【刷题-LeetCode】289. Game of Life

    Game of Life According to the Wikipedia's article: "The Game of Life, also known simply as Life ...