在我们的工作中,很多地方使用延迟队列,比如订单到期没有付款取消订单,制订一个提醒的任务等都需要延迟队列,那么我们需要实现延迟队列。我们本文的梗概如下,同学们可以选择性阅读。

1. 实现一个简单的延迟队列。

我们知道目前JAVA可以有DelayedQueue,我们首先开一个DelayQueue的结构类图。DelayQueue实现了Delay、BlockingQueue接口。也就是DelayQueue是一种阻塞队列。

我们在看一下Delay的类图。Delayed接口也实现了Comparable接口,也就是我们使用Delayed的时候需要实现CompareTo方法。因为队列中的数据需要排一下先后,根据我们自己的实现。Delayed接口里边有一个方法就是getDelay方法,用于获取延迟时间,判断是否时间已经到了延迟的时间,如果到了延迟的时间就可以从队列里边获取了。

我们创建一个Message类,实现了Delayed接口,我们主要把getDelay和compareTo进行实现。在Message的构造方法的地方传入延迟的时间,单位是毫秒,计算好触发时间fireTime。同时按照延迟时间的升序进行排序。我重写了里边的toString方法,用于将Message按照我写的方法进行输出。

里边的main方法里边声明了两个Message,一个延迟5秒,一个延迟7秒,时间到了之后会将接取出并且打印。输出的结果如下,正是我们所期望的。

这个方法实现起来真的非常简单。但是缺点也是很明显的,就是数据在内存里边,数据比较容易丢失。那么我们需要采用Redis实现分布式的任务处理。

2. 使用Redis的list实现分布式延迟队列。

本地需要安装一个Redis,我自己是使用Docker构建一个Redis,非常快速,命令也没多少。我们直接启动Redis并且暴露6379端口。进入之后直接使用客户端命令即可查看和调试数据。

我本地采用spring-boot的方式连接redis,pom文件列一下,供大家参考。

加上Redis的配置放到application.properties里边即可实现Redis连接,非常的方便。

接下来实现一个基于Redis的list数据类型进行实现的一个类。我们使用RedisTemplate操作Redis,这个里边封装好我们所需要的Redis的一些方法,用起来非常方便。这个类允许延迟任务做多有10W个,也是避免数据量过大对Redis造成影响。如果在线上使用的时候也需要考虑延迟任务的多少。太多几百万几千万的时候可能数据量非常大,我们需要计算Redis的空间是否够。这个代码也是非常的简单,一个用于存放需要延迟的消息,采用offer的方法。另外一个是启动一个线程, 如果消息时间到了,那么就将数据lpush到Redis里边。

接下来我们看一下,我们写一个测试的controller。大家看一下这个请求/redis/listDelayedQueue的代码位置。我们也是生成了两个消息,然后把消息放到队列里边,另外我们在启动一个线程任务,用于将数据从Redis的list中获取。方法也非常简单。

我就不把运行结果写出来了,感兴趣的同学自己自行试验。当然这个方法也是从内存中拿出数据,到时间之后放到Redis里边,还是会存在程序启动的时候,任务进行丢失。我们继续看另外一种方法更好地进行这个问题的处理。

3. 使用Redis的zSet实现分布式延迟队列。

我们需要再写一个ZSet的队列处理。下边的offerMessage主要是把消息直接放入缓存中。采用Redis的ZSET的zadd方法。zadd(key, value, score) 即将key=value的数据赋予一个score, 放入缓存中。score就是计算出来延迟的毫秒数。

上边的Controller方法已经写好了测试的方法。/redis/zSetDelayedQueue,里边主要使用ZSet的zRangeByScore(key, min, max)。主要是从score从0,当前时间的毫秒数获取。取出数据后再采用removeRangeByScore,将数据删除。这样数据可以直接写到Redis里边,然后取出数据后直接处理。这种方法比前边的方法稍微好一些,但是实际上还存在一些问题,因为依赖Redis,如果Redis内存不足或者连不上的时候,系统将变得不可用。

4. 总结一下,另外还有哪些可以延迟队列。

上面的方法其实还是存在问题的,比如系统重启的时候还是会造成任务的丢失。所以我们在生产上使用的时候,我们还需要将任务保存起来,比如放到数据库和文件存储系统将数据存储起来,这样做到double-check,双重检查,最终达到任务的99.999%能够处理。

其实还有很多东西可以实现延迟队列。

1) RabbitMQ就可以实现此功能。这个消息队列可以把数据保存起来并且进行处理。

2)Kafka也可以实现这个功能。

3)Netty的HashedWheelTimer也可以实现这个功能。

有兴趣的同学可以进一步研究这些内容的实现。

欢迎大家留言评论,做进一步探讨!

java 延时队列_Java实现简单延迟队列和分布式延迟队列相关推荐

  1. rockemq 发送延迟消息_58分布式消息队列WMB设计与实践

    背景 为了能够承载58业务的快速扩展及海量的用户访问,分布式系统已经成为公司一种主流架构设计.而消息队列是大型分布式系统中不可或缺的通信桥梁,在分布式系统解耦.异步通信.事件通知.流量削峰等业务场景中 ...

  2. java延时执行_Java谓词的延迟执行

    java延时执行 在先前的文章" 用Java的供应商延迟执行 "和" Java的消费者延迟执行 ",我看着很容易地通过推迟标准Java API接受,分别在Jav ...

  3. mysql 消息队列_一个简单的 MySQL 批量事务消息队列

    基于 MySQL 的批量事务消息队列 消息队列本质上是一个存储介质,通常是链表结构,不同的进程或线程可以向消息队列中写入或读取消息.消息队列的使用场景有很多,比如异步处理任务.应用解耦.流量削锋等等. ...

  4. java gui 日历_Java实现简单日历小程序 Java图形界面小日历开发

    今天给大家介绍一下如何用Java swing开发一款简单的小日历,下面我们来看代码: 首先创建一个CalendarBean类,用于基本的日期计算: package other1; import jav ...

  5. java 日历界面_Java实现简单日历小程序 Java图形界面小日历开发

    今天给大家介绍一下如何用java swing开发一款简单的小日历,下面我们来看代码: 首先创建一个calendarbean类,用于基本的日期计算: package other1; import jav ...

  6. java银行取款_Java写简单的银行取钱系统

    按ctrl+a 选中所有的代码删除,再复制下面的代码输入即可 import java.util.Scanner; public class 简单的银行取钱系统 //class的名字可以自己新建和这个一 ...

  7. java多线程队列_java多线程消费者生产者模式(BlockingQueue 通过阻塞队列实现)

    import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; /** * Cr ...

  8. java 简单阻塞队列,制作一个简单的任务队列(使用阻塞队列)

    充分利用阻塞队列的特性,队列中没有任务时,让线程阻塞.代码如下: import java.util.concurrent.BlockingQueue; import java.util.concurr ...

  9. java 通信 教程_Java实现简单的socket通信教程

    今天学习了一下java如何实现socket通信,感觉难点反而是在io上,因为java对socket封装已经很完善了. 今天代码花了整个晚上调试,主要原因是io的flush问题和命令行下如何运行具有pa ...

最新文章

  1. 多态基类与虚析构函数
  2. Android 获取当前日期距离过期时间的日期差值的完整方法直接使用
  3. UML博客建模--用例图
  4. 【Python】集合的交、并、补、差集怎么算?
  5. 关于线程池,那些你还不知道的事
  6. 解决wiremock中velocity脚本(.vm)中文编码乱码问题
  7. 使用JavaScript给对象修改注册监听器
  8. [Swift]LeetCode264.丑数 II | Ugly Number II
  9. 最简单DIY基于STM32F407探索者开发板和PCA9685舵机控制模块的红外遥控机械臂控制程序
  10. php中医处方系统简介
  11. 万亿市场的广场舞未来在哪里?
  12. 怎么压缩PPT大小?
  13. 绘制confusion matrix的R实现
  14. 使用C#开发纽曼USB来电通来电弹屏客户端小结
  15. 黑苹果制作Clover开机引导脱离U盘,小新Pro13详细教程
  16. c语言自己走时间的程序,c语言用哪些语句能实现时间暂停?比方说按某一个键使时间暂停,再按一次使时间继续。...
  17. 计算机的未来展望英语作文,关于展望未来英语作文5篇
  18. https://wenku.baidu.com/view/35c88b375acfa1c7aa00ccca.html--swot
  19. Picker 选择器
  20. 无人驾驶车辆运动规划方法综述

热门文章

  1. WINCC与STEP7的仿真连接_过路老熊_新浪博客
  2. 博图软件中多重背景块的建立_过路老熊_新浪博客
  3. 数据库 和 数据仓库
  4. 电商直播元年 微媒云播打造私域流量火爆商业新模式
  5. 计蒜客 ACM训练联盟周赛 第一场 从零开始的神棍之路 暴力dfs
  6. 毕设论文数据分析记录-part2:相关性分析
  7. python语言的注释语句引导符不包括什么_以下选项中,哪一个是Python语言中代码注释使用的符号?________...
  8. 程序员写程序的逻辑思维,和外行人想当然的思维,到底有什么不同
  9. springboot系列课程笔记-第四章-WEB开发
  10. 2023-2028年中国黄酒行业市场预测与投资规划分析报告