如何通过DelayQueue实现延时任务

延迟队列DelayQueue原理 前言 什么是DelayQueue(延时队列) DelayQueue 是一个通过PriorityBlockingQueue实现延迟获取元素的无界队列无界阻塞队列,其中添加进该队列的元素必须实现Delayed接口(指定延迟时间),而且只有在延迟期满后才能从中提取元素。 什么是PriorityBlockingQueue(优先队列) PriorityBlockingQueue是一个支持优先级的无界阻塞队列,队列的元素默认情况下元素采用自然顺序升序排列,或者根据构造队列时提供的 Comparator 进行排序,具体取 阅读详情

一、DelayQueue的应用原理

DelayQueue是一个无界的BlockingQueue的实现类,用于放置实现了Delayed接口的对象,其中的对象只能在其到期时才能从队列中取走。

  • BlockingQueue即阻塞队列,java提供的面向多线程安全的队列数据结构,当队列内元素数量为0的时候,试图从队列内获取元素的线程将被阻塞或者抛出异常。

  • 这里的“无界”队列,是指队列的元素数量不存在上限,队列的容量会随着元素数量的增加而扩容。

DelayQueue实现了BlockingQueue接口,所以具有无界、阻塞的特点,除此之外它自己的核心特点就是:

  • 「放入该队列的延时任务对象,只要到达延时时间之后才能被取到」。

  • DelayQueue 不接收null元素

  • 「DelayQueue 只接受那些实现了java.util.concurrent.Delayed接口的对象」

二、订单延时任务的实现

了解了DelayQueue的特点之后,我们就可以利用它来实现延时任务了,实现java.util.concurrent.Delayed接口。

import org.jetbrains.annotations.NotNull;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

/**
 * 延时订单任务
 */
public class OrderDelayObject implements Delayed {
  private String name;
  private long delayTime;   //延时时间
  //实际业务中这里传订单信息对象,我这里只做demo,所以使用字符串了
  private String order;

  public OrderDelayObject(String name, long delayTime, String order) {
    this.name = name;
    //延时时间加上当前时间
    this.delayTime = System.currentTimeMillis() + delayTime;
    this.order = order;
  }

  //获取延时任务的倒计时时间
  @Override
  public long getDelay(TimeUnit unit) {
    long diff = delayTime - System.currentTimeMillis();
    return unit.convert(diff, TimeUnit.MILLISECONDS);
  }

  //延时任务队列,按照延时时间元素排序,实现Comparable接口
  @Override
  public int compareTo(@NotNull Delayed obj) {
    return Long.compare(this.delayTime, ((OrderDelayObject) obj).delayTime);
  }

  @Override
  public String toString() {
    Date date = new Date(delayTime);
    SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    return "\nOrderDelayObject:{"
            + "name=" + name
            + ", time=" + sd.format(date)
            + ", order=" + order
            + "}";
  }
} 


  • 上文类中的order为订单信息对象,在实际的业务开发过程中应该是传递订单信息,用于取消订单业务的实现(订单30分钟不付款自动取消)。

  • Delayed接口继承自 Comparable接口,所以需要实现compareTo方法,用于延时任务在队列中按照“延时时间”进行排序。

  • getDelay方法是Delayed接口方法,实现该方法提供获取延时任务的倒计时时间

三、订单处理

首先我们需要一个容器,永久保存延时任务队列,如果是Spring开发环境我们可以这样做。

@Bean("orderDelayQueue")
public DelayQueue<OrderDelayObject> orderDelayQueue(){
    return new DelayQueue<OrderDelayObject>();
}


当用户下单的时候,将订单下单任务放入延时队列

@Resource
private DelayQueue<OrderDelayObject> orderDelayQueue;

//发起订单下单的时候将订单演示对象放入orderDelayQueue
orderDelayQueue.add(
        new OrderDelayObject(
                "订单延时取消任务",
                30 * 60 * 1000,    //延时30分钟
                "延时任务订单对象信息"
        )
);


系统内开启一个线程,不断的从队列中获取消息,获取到之后对延时消息进行处理。DelayQueue的take方法从队列中获取延时任务对象,如果队列元素数量为0,或者没有到达“延时时间的任务”,该线程会被阻塞。

@Component
public class DelayObjectConsumer  implements InitializingBean {

  @Resource
  private DelayQueue<OrderDelayObject> orderDelayQueue;

  @Override
  public void afterPropertiesSet() throws Exception {
    while (true) {
      OrderDelayObject task = orderDelayQueue.take();
      System.out.println(task.toString());
      System.out.println(task.getOrder());
      //根据order订单信息,去查询该订单的支付信息
      //如果用户没有进行支付,将订单从数据库中关闭
      //如果订单并发量比较大,这里可以考虑异步或线程池的方式进行处理
    }
  }
}


需要说明的是,这里的while-true循环的延时任务处理是顺序执行的,在订单并发量比较大的时候,需要考虑异步处理的方式完成订单的关闭操作。

四、优缺点 

使用DelayQueue实现延时任务非常简单,而且简便,全部都是标准的JDK代码实现,不用引入第三方依赖(不依赖redis实现、消息队列实现等),非常的轻量级。

它的缺点就是所有的操作都是基于应用内存的,一旦出现应用单点故障,可能会造成延时任务数据的丢失。如果订单并发量非常大,因为DelayQueue是无界的,订单量越大,队列内的对象就越多,可能造成OOM的风险。所以使用DelayQueue实现延时任务,只适用于任务量较小的情况。

DelayQueue源码解析 DelayQueue是JUC包(java.util.concurrent)为我们提供的延迟队列,它是一个基于PriorityQueue实现的一个无界队列,是一个线程安全的延迟队列。PriorityQueue源码分析当我们希望某个任务在某个时间才能取出并操作时,我们就可以让这个继承Delayed接口,实现其计算任务到期时间的方法 getDelay。然后将任务存放到 DelayQueue 中,默认情况下, DelayQueue 会按照到期时间升序编排任务。 阅读详情

相关推荐

完整实现-通过DelayQueue实现延时任务

它的缺点就是所有的操作都是基于应用内存的,一旦出现应用单点故障,可能会造成延时任务数据的丢失。如果订单并发量非常大,因为DelayQueue是无界的,订单量越大,队列内的对象就越多,可能造成OOM的风险。需要说明的是,这里的while-true循环的延时任务处理时顺序执行的,在订单并发量比较大的时候,需要考虑异步处理的方式完成订单的关闭操作。使用DelayQueue实现延时任务非常简单,而且简便,全部都是标准的JDK代码实现,不用引入第三方依赖(不依赖redis实现、消息队列实现等),非常的轻量级。

m0_67698950的博客 373

DelayQueue详解

DelayQueue 也是 Java 并发包()中的一个特殊队列,用于在指定的延迟时间之后处理元素。

落日的博客 3396

破局延时任务 Spring Boot + DelayQueue 优雅实现分布式延时队列实战

本文介绍了一个基于SpringBoot和DelayQueue的分布式延时任务组件实现方案。该组件采用模块化设计,包括协调服务、任务存储、任务处理器和分布式延时队列四大核心模块,实现了任务准时触发、分布式协调、数据持久化和高可用性等核心功能。通过Redis实现任务存储和集群协调,利用DelayQueue确保毫秒级延时精度,并设计了多级防护机制防止任务重复执行。组件支持水平扩展,具备优雅启停、资源隔离和智能负载均衡等特性,已具备生产环境使用条件。未来可通过集成监控告警、开发管理界面等方式进一步优化系统功能。

wjianwei666的专栏 150

阻塞队列-DelayQueue详解

DelayQueue 是一个支持延时获取元素的阻塞队列, 内部采用优先队列 PriorityQueue 存储元素,同时元素必须实现 Delayed 接口;在创建元素时可以指定多久才可以从队列中获取当前元素,只有在延迟期满时才能从队列中提取元素。延迟队列的特点是:不是先进先出,而是会按照延迟时间的长短来排序,下一个即将执行的任务会排到队列的最前面。

wssc63262的博客 3210

延时任务通知服务的设计及实现(三)-- JDK的延迟队列DelayQueue

作为进程内的延迟队列,在多点部署的分布式集群环境下, 代码明显比上一篇要复杂得多。任务的生产任务的消费移除任务应用启动的时候拉取回调时间将近的未完成任务(更新marked标记为true,防止重复拉取冷数据)定时拉取未标记且回调时间将近的未完成任务(和上面必须是互斥,等待上一步执行完成,否则会导致重复拉取)删除延迟队列DelayQueue的任务,必须发布广播消息给全部节点。(引入广播消息机制)

天草二十六 1473

vietjetair 航空的webpack多参数生成学习

工作内不是特别多,居安思危,有一个抓机票信息的公司面试前竟然需要做面试题,这就是一个题。看了下,有点麻烦,webpack 最初不得要领,看了下资料,找了个框架,练了两个简单的,搞这个吧。入库需要自己找,有几个参数不是明文的,算法不是很复杂,位置不太好找。整体难度一般。

liu_yueyang的博客 1510

Java阻塞延迟队列DelayQueue原理及使用

DelayQueue队列中每个元素都有一个过期时间,并且队列是个优先级队列,当从队列获取元素的时候,只有过期元素才会出队。

Hopefully Sky的博客 1万+

手把手教你理解特斯拉Model 3的域控制器架构:RBCM如何成为“多面手”?

本文深入解析特斯拉Model 3的域控制器架构,重点介绍右车身域控制器(RBCM)如何整合车身电子系统功能。RBCM作为多任务处理中枢,管理空调系统、尾部电气设备和超声波雷达等关键功能,展现了特斯拉在汽车电子架构上的创新设计。文章详细探讨了RBCM的硬件架构、功能版图及信号网络,揭示其如何通过高性能MCU和智能开关技术实现功能集中与效率提升。

weixin_30919429的博客 379

完整实现 - 通过 DelayQueue 实现延时任务

一、DelayQueue 的应用原理二、订单延时任务的实现三、订单处理四、优缺点实现延时任务有很多的方法,网上关于延时任务的实现的文章已经不少了。比如:实现延时任务的 10 种方法等等。但是这些文章基本上都是将方法大概的列举一下,给出部分示例代码,对于有经验的老程序员可能一看就知道该怎么去把它实现完整,但是对于初学者来说不够友好。所以,。小概念:什么是延时任务?举个例子:你买了一张火车票,必须在 30 分钟之内付款,否则该订单被自动取消。

AS011x的博客 254

从零开始理解二极管限幅:5种典型电路设计及实际应用场景解析

本文系统解析了二极管限幅电路的五大经典拓扑,包括串联与并联型上下限幅及双向限幅。通过剖析其核心原理与二极管的单向导电性、正向压降特性,结合ADC输入保护、电源管理、音频处理等实际应用场景,提供了从器件选型到设计陷阱规避的完整实战指南,帮助工程师为信号构建可靠的“安全笼”。

2y3u4i5o6p的博客 1034

别再用MounRiver了!在VSCode里用PlatformIO搞定CH32V208开发(附完整配置流程)

本文详细介绍了如何在VSCode中使用PlatformIO进行CH32V208开发,替代传统的MounRiver Studio。通过完整的配置流程和优化技巧,开发者可以构建高效、现代化的RISC-V开发环境,显著提升编译速度和开发效率。

weixin_28711397的博客 533

java延时_Java实现延时任务——DelayQueue

应用开发过程中,我们常常需要用到延时任务的地方,举个栗子:在我们提交订单之后,15分钟内未支付则需要自动取消订单,当然,实现的方式有很多种,我们尝试用延时任务方式进行。java里自带的延时队列——DelayQueue即可实现。什么是DelayQueueDelayQueue——延时队列,提供了在指定时间才能获取队列元素的功能。也就是说只有在队列加入元素后指定时间间隔后才能取出元素。DelayQueu...

weixin_36480510的博客 3233

scRNA-seq | 吐血整理的单细胞入门教程(从原理到代码实操)(二)

scRNA-seq | 吐血整理的单细胞入门教程(从原理到代码实操)(二)

m0_72224305的博客 4305

DelayQueue实现Java延时任务

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34115824的博客 306

(持续更新中!)详解【计算机类&面试真题】军队文职考试 ——第二期(真题+解析)| 网络协议的三个核心要素;交互式系统中的非剥夺策略;中断和陷入的区别;可变分区管理中的硬件机制;数据库系统的优点

本篇博客将讨论军队文职面试(计算机类)的几个关键问题。我们将介绍网络协议的核心要素(帮助你理解网络通信的基本原理)、交互式系统中的非剥夺策略(解释为何这是一个优秀的策略以及其对用户体验、系统稳定性和可预测性的影响)、中断和陷入的区别(从引起原因、处理机制、权限级别和应用等方面进行阐述)、可变分区管理的硬件机制以及数据库系统与文件系统的优点比较。通过阅读本文,您将深入了解这些话题,为面试准备和实际应用提供有价值的知识。

追光者♂:记录、分享、总结、提升,现象级专栏《Python从入门到人工智能》作者,无惧黑暗,坚信曙光 1705

<PLC><西门子><工控>西门子博图V18中使用SCL语言编写一个CRC16-modbus校验程序

西门子官方对于SCL语言的介绍如下:SCL 编程语言SCL 编程语言SCL(Structured Control Language,结构化控制语言)是一种基于 PASCAL 的高级编程语言。这种语言基于标准DIN EN 61131-3(国际标准为 IEC 1131-3)。根据该标准,可对用于可编程逻辑控制器的编程语言进行标准化。SCL 编程语言实现了该标准中定义的 ST 语言 (结构化文本) 的PLCopen 初级水平。语言元素。

用沸腾的热血,支付我们的人生吧! 1436

使用DelayQueue的实现延时任务

延迟执行DelayQueue的使用!

weixin_44203609的博客 380

滑模观测器与锁相环结合应用:让电机“无感”也能精准旋转的奥秘

本文介绍了永磁同步电机无传感器控制中的滑模观测器(SMO)结合锁相环(PLL)技术。SMO通过创建虚拟电机模型,利用电流误差产生控制信号来估计反电动势;PLL则从反电动势中解码转子位置和速度信息。该组合方案兼具SMO的鲁棒性和PLL的高精度,计算量小且硬件要求低。文章详细阐述了原理、数学模型、参数整定方法及实际实现技巧,包括离散化处理、符号函数替代等优化手段,并分析了低速性能限制、抖振问题等常见挑战及解决方案。最后指出该技术未来将与人工智能、多观测器融合等方向结合发展。

汽车软件开发 193

破局延时任务(下):Spring Boot + DelayQueue 优雅实现分布式延时队列(实战篇)

本文详细介绍了基于Spring Boot和DelayQueue的分布式延时队列组件实现方案。文章首先回顾了上篇提出的架构设计,包含协调服务、任务存储、任务处理器和分布式延时队列四大核心模块。重点阐述了组件实现细节,包括延时任务实体封装、任务处理器接口设计,以及基于Redis的任务存储层实现。通过实现Delayed接口的任务实体类和统一的任务存储接口,保证了任务的不丢失、不重复和准时执行特性。文章展示了如何将内存队列与持久化存储结合,构建高性能、高可用的分布式延时任务系统。

weixin_41821642的博客 865

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

java定时任务的另一种实现---延时队列(DelayQueue)

文章目录java定时任务的另一种实现---延时队列(DelayQueue)一、DelayQueue介绍二、实例演示1、定义一个Delayed子类2、main方法3、常用方法说明4、原理解析 java定时任务的另一种实现—延时队列(DelayQueue) 一、DelayQueue介绍 类签名: public class DelayQueue<E extends Delayed> extends AbstractQueue<E> implements BlockingQueue<

qq15887345的博客 1728

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

springboot执行延时任务-DelayQueue的使用

DelayQueue简介 在很多场景我们需要用到延时任务,比如给客户异步转账操作超时后发通知告知用户,还有客户下单后多长时间内没支付则取消订单等等,这些都可以使用延时任务来实现。 jdk中DelayQueue可以实现上述需求,顾名思义DelayQueue就是延时队列。 DelayQueue提供了在指定时间才能获取队列元素的功能,队列头元素是最接近过期的元素。 没有过期元素的话,使用...

weixin_44626952的博客 3565

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

延时队列DelayQueue

DelayQueue是一个无界的BlockingQueue(线程安全),用于放置实现了Delayed接口的对象,其中的对象只能在其到期时才能从队列中取走。这种队列是有序的,即队头对象的延迟到期时间最长。通俗地讲,(延时队列也是队列的一种,遵循先进先出的特点)要将延时队列和定时任务区分开!!!:在特定时间执行任务。

Yangyeon_的博客 2299
上一篇: Spring 源码阅——忽略感知接口对应成员变量的自动装配
下一篇: 还搞不懂性能调优?让你见识这份《Java性能调优PDF》啃完你就知道多厉害了!
Java_ttcd
博客等级 码龄4年 198粉丝 190原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值