0

0

Java DelayQueue怎么实现延时任务

WBOY

WBOY

发布时间:2023-05-13 16:40:06

|

1874人浏览过

|

来源于亿速云

转载

一、DelayQueue的应用原理

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

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

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

Java DelayQueue怎么实现延时任务

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

立即学习Java免费学习笔记(深入)”;

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

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分钟不付款自动取消)。

Audo Studio
Audo Studio

AI音频清洗工具(噪音消除、声音平衡、音量调节)

下载

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

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

三、订单处理

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

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

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

@Resource
private DelayQueue orderDelayQueue;

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

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

@Component
public class DelayObjectConsumer  implements InitializingBean {

  @Resource
  private DelayQueue 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循环的延时任务处理是顺序执行的,在订单并发量比较大的时候,需要考虑异步处理的方式完成订单的关闭操作。我之前写过一个SpringBoot的可观测、易配置的线程池开源项目,可能会对你有帮助,源代码地址

经过我的测试,放入orderDelayQueue的延时任务,在半小时之后得到正确的执行处理。说明我们的实现是正确的。

四、优缺点

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

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

相关文章

java速学教程(入门到精通)
java速学教程(入门到精通)

java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
菜鸟裹裹入口以及教程汇总
菜鸟裹裹入口以及教程汇总

本专题整合了菜鸟裹裹入口地址及教程分享,阅读专题下面的文章了解更多详细内容。

0

2026.01.22

Golang 性能分析与pprof调优实战
Golang 性能分析与pprof调优实战

本专题系统讲解 Golang 应用的性能分析与调优方法,重点覆盖 pprof 的使用方式,包括 CPU、内存、阻塞与 goroutine 分析,火焰图解读,常见性能瓶颈定位思路,以及在真实项目中进行针对性优化的实践技巧。通过案例讲解,帮助开发者掌握 用数据驱动的方式持续提升 Go 程序性能与稳定性。

9

2026.01.22

html编辑相关教程合集
html编辑相关教程合集

本专题整合了html编辑相关教程合集,阅读专题下面的文章了解更多详细内容。

56

2026.01.21

三角洲入口地址合集
三角洲入口地址合集

本专题整合了三角洲入口地址合集,阅读专题下面的文章了解更多详细内容。

51

2026.01.21

AO3中文版入口地址大全
AO3中文版入口地址大全

本专题整合了AO3中文版入口地址大全,阅读专题下面的的文章了解更多详细内容。

397

2026.01.21

妖精漫画入口地址合集
妖精漫画入口地址合集

本专题整合了妖精漫画入口地址合集,阅读专题下面的文章了解更多详细内容。

118

2026.01.21

java版本选择建议
java版本选择建议

本专题整合了java版本相关合集,阅读专题下面的文章了解更多详细内容。

3

2026.01.21

Java编译相关教程合集
Java编译相关教程合集

本专题整合了Java编译相关教程,阅读专题下面的文章了解更多详细内容。

16

2026.01.21

C++多线程相关合集
C++多线程相关合集

本专题整合了C++多线程相关教程,阅读专题下面的的文章了解更多详细内容。

11

2026.01.21

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 2.8万人学习

C# 教程
C# 教程

共94课时 | 7.3万人学习

Java 教程
Java 教程

共578课时 | 49.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号