springboot +java延时任务(Delayed)

java实现延迟/超时/定时 方法获取任务的时候,会拿到队列头部的元素,也就是队列中最早需要被执行的任务,通过getDelay返回值判断任务是否需要被立刻执行,如果需要的话,就返回任务,如果不需要就会等待这个任务到延迟时间的剩余时间,当时间到了就会将任务返回。,list数据类型,被称为目标队列,这个里面存放的任务都是已经到了延迟时间的,可以被消费者获取的任务,所以上面demo中的RBlockingQueue的take方法是从这个目标队列中获取到任务的。这里面就有这么一个channel叫做。图中channel理解成MQ中的topic。 阅读详情

问题场景:
订单超时自动取消,类似淘宝或者美团等购买商品时,在用户没有按照规定时间付款时,订单会在指定时间取消。

解决办法:
1.定时任务:该方案通常是在小型项目中使用,即通过一个线程定时的去扫描数据库,通过订单时间来判断是否有超时的订单,然后进行update或delete等操作(quartz来实现
2.基于RabbitMQ实现,借助于RabbitMQ的延迟队列TTL和死信队列。
3.JDK的延迟队列
该方案是利用JDK自带的DelayQueue来实现,这是一个无界阻塞队列,该队列只有在延迟期满的时候才能从中获取元素,放入DelayQueue中的对象,是必须实现Delayed接口的。
其中Poll():获取并移除队列的超时元素,没有则返回空
take():获取并移除队列的超时元素,如果没有则wait当前线程,直到有元素满足超时条件,返回结果
4.redis缓存
思路一利用redis的zset,zset是一个有序集合,每一个元素(member)都关联了一个score,通过score排序来取集合中的值
添加元素:ZADD key score member [[score member] [score member] …]
按顺序查询元素:ZRANGE key start stop [WITHSCORES]
查询元素score:ZSCORE key member
移除元素:ZREM key member [member …]
以上都是可以解决此场景。
今天重点说一下java延时队列(Delayed)
话不多说,直接上代码
1.controller层
注意:使用 @Autowired进行使用

public class OrderController extends BaseController {

    private final ITOrderService iTOrderService;

    @Autowired
    private DelayQueueManagers delayQueueManager;
/**
     * 新增订单管理
     */
    @ApiOperation(value="新增订单")
//    @PreAuthorize("@ss.hasPermi('manage:order:add')" )
    @Log(title = "订单管理" , businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody TOrder tOrder) throws ParseException {
        Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(DateUtils.getTime());
        tOrder.setFinshtime(date);
        tOrder.setCreatetime(date);
        tOrder.setPaytime(date);
        tOrder.setUpdatetime(date);
        delayQueueManager.put(new DelayTask(new TaskBase(tOrder.getOid().toString()),1000*60*1));//新增任务
        return toAjax(iTOrderService.save(tOrder) ? 1 : 0);
    }

2.定义延迟队列管理类DelayQueueManagers
注意:必须加@Component,注入到spring

package com.nft.shop.test;
import com.nft.manage.service.ITOrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Executors;

@Component
@Slf4j
public class DelayQueueManagers implements CommandLineRunner {

    private final DelayQueue<DelayTask> delayQueue = new DelayQueue<>();

    @Autowired
    private ITOrderService iTOrderService;

    /**
     * 加入到延时队列中
     * @param task
     */
    public void put(DelayTask task) {
        log.error("加入延时任务:{}", task);
        delayQueue.put(task);
    }
    /**
     * 取消延时任务
     * @param task
     * @return
     */
    public boolean remove(DelayTask task) {
        log.error("取消延时任务:{}", task);
        return delayQueue.remove(task);
    }
    /**
     * 取消延时任务
     * @param taskid
     * @return
     */
    public boolean remove(String taskid) {
        return remove(new DelayTask(new TaskBase(taskid), 0));
    }
    @Override
    public void run(String... args) throws Exception {
        log.info("初始化延时队列");
        Executors.newSingleThreadExecutor().execute(new Thread(this::excuteThread));
    }
    /**
     * 延时任务执行线程
     */
    private void excuteThread() {
        while (true) {
            try {
                DelayTask task = delayQueue.take();
                processTask(task);
            } catch (InterruptedException e) {
                break;
            }
        }
    }
    /**
     * 内部执行延时任务
     * @param task
     */
    private void processTask(DelayTask task) {
        log.error("执行延时任务:{}-{}", task,task.getData().getIdentifier());
        List<Map> list = iTOrderService.queryOrderTimerStatus();
        if (!CollectionUtils.isEmpty(list)) {
            for (int i = 0; i < list.size(); i++) {
                iTOrderService.updateOrderTimerStatus((Integer) list.get(i).get("oId"));
            }
        }
    }
}

3.taskBase

package com.nft.shop.test;

public class TaskBase {
    private String identifier;

    public TaskBase(String identifier) {
        this.identifier = identifier;
    }

    public String getIdentifier() {
        return identifier;
    }

    public void setIdentifier(String identifier) {
        this.identifier = identifier;
    }

}

4.DelayTask

package com.nft.shop.test;
import com.nft.common.utils.DateUtils;

import java.util.Date;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
public class DelayTask implements Delayed {

    final private TaskBase data;

    final private long expire;

    /**
     * 构造延时任务
     *
     * @param data   业务数据
     * @param expire 任务延时时间(ms)
     */
    public DelayTask(TaskBase data, long expire) {
        super();
        this.data = data;
        this.expire = expire + System.currentTimeMillis();
    }

    public TaskBase getData() {
        return data;
    }

    public long getExpire() {
        return expire;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof DelayTask) {
            return this.data.getIdentifier().equals(((DelayTask) obj).getData().getIdentifier());
        }
        return false;
    }

    @Override
    public String toString() {
        return "{" + "data:" + data.toString() + "," + "延时时间:" + DateUtils.getTimestampToTime(expire,DateUtils.YYYY_MM_DD_HH_MM_SS) + "}";
    }

    @Override
    public long getDelay(TimeUnit unit) {
        return unit.convert(this.expire - System.currentTimeMillis(), unit);
    }

    @Override
    public int compareTo(Delayed o) {
        long delta = getDelay(TimeUnit.NANOSECONDS) - o.getDelay(TimeUnit.NANOSECONDS);
        return (int) delta;
    }
}

其中用了格式化日期

public class DateUtils extends org.apache.commons.lang3.time.DateUtils
{

  public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";


  public static String getTimestampToTime(Long timeStamp,final String ts){
      SimpleDateFormat sdf=new SimpleDateFormat(ts);
      return sdf.format(new Date(Long.parseLong(String.valueOf(timeStamp))));
  }
  }
SpringBoot+RabbitMQ使用插件实现延时队列 延时队列 在实际业务场景中可能会用到延时消息发送,例如支付场景,准时支付、超过未支付将执行不同的方案,其中超时未支付可以看做一个延时消息。 延时队列的使用场景: 1.订单业务:在电商中,用户下单后30分钟后未付款则取消订单。 2.短信通知:用户下单并付款后,1分钟后发短信给用户。 最常用到方式为定时任务轮训,数据量小的时候使用没什么问题 而当有千万甚至上亿的数据量时就会出现数据读取的瓶颈,此... 阅读详情

相关推荐

springboot执行延时任务之DelayQueue的使用详解

DelayQueue是一个无界阻塞队列,只有在延迟期满时,才能从中提取元素。这篇文章主要介绍了springboot执行延时任务-DelayQueue的使用,需要的朋友可以参考下

Java使用 Delayed 实现延迟任务

创建一个 Delayed 抽象类并且实现Runnable接口 /** * 延迟任务抽象 */ public abstract class Task implements Delayed, Runnable{ private String id = ""; private long start = 0; /** * * @param id 任务ID, 用于区分不同任务 * @param delayInMilliseconds 延迟毫秒 *

半只 5194

java利用delayedQueue实现本地的延迟队列

主要给大家介绍了java利用delayedQueue实现本地的延迟队列的相关资料,文中介绍的非常详细,相信对大家具有一定的参考价值,需要的朋友们下面来一起看看吧。

java delayed实例_Java延迟队列原理与用法实例详解

本文实例讲述了Java延迟队列原理与用法。分享给大家供大家参考,具体如下:延时队列,第一他是个队列,所以具有对列功能第二就是延时,这就是延时对列,功能也就是将任务放在该延时对列中,只有到了延时时刻才能从该延时对列中获取任务否则获取不到……应用场景比较多,比如延时1分钟发短信,延时1分钟再次执行等,下面先看看延时队列demo之后再看延时队列在项目中的使用:简单的延时队列要有三部分:第一实现了Dela...

weixin_30346649的博客 2614

基于TI C2000的CCS安装与工程创建完整示例

手把手演示基于TI C2000系列的CCS安装过程及首个工程创建步骤,涵盖环境配置与常见问题处理,助力快速上手嵌入式开发,ccs安装和工程搭建不再难。

weixin_42476987的博客 967

802.11ax 的OFDMA资源分配详解

802.11ax 引入的最重要的技术就是OFDMA。OFDMA中引入了RU(资源块)概念,也就是20Mhz/40Mhz/80Mhz/160Mhz的带宽可以切割成不同尺寸的RU,分配给不同的用户使用,这样就大大提高了频谱资源的利用率。 常见的RU尺寸有26/52/102/242/484/996,单位是子载波,每个子载波是78.125Khz,这样20Mhz的带宽可以划分为如下图所示的不同RU大小。 按照11ax规范的要求,上下行的数据传输都可以由AP来统一调度,这样上下行的OFDM...

weixin_43408952的博客 1万+

记录Delay延时队列的使用

记录Delay延时队列的使用场景延时队列DelayQueue源码结合springboot简单应用 场景 在公司业务场景中,偶然出现了一个量较小的需求:在某个业务系统处理完成之后,需要做一个临时操作,例如:用户申请某web网页账号后给用户指定账号发送一份邮件提示用户账号已开通… 等等,如果跟业务系统耦合,会影响到业务处理的速度,本来想用MQ做一个队列处理消息,但是系统消息量不大,尝试使用原生API DelayQueue延时队列实现。 延时队列DelayQueue java.util包中提供了现成的轮子,先扒一

qq_37216641的博客 550

AD5700 HART芯片实战笔记:从时钟检测到数据收发,一个STM32工程师的踩坑实录

本文详细记录了STM32工程师在AD5700 HART芯片开发中的实战经验,涵盖时钟信号检测、RTS切换时序优化及HART数据解析等关键问题。通过硬件设计检查、定时器配置优化和大小端转换方案对比,解决了工业级芯片开发中的典型挑战,为嵌入式开发者提供宝贵参考。

weixin_42715608的博客 164

springBoot之延时队列

1、创建延时队列 package com.example.demo.utils; import lombok.Data; import java.util.concurrent.DelayQueue; /** * 延时队列 * 需要保证队列单例 */ @Data public class DelayTaskQueue { private static class Holder{ static DelayQueue<DelayTask> instance = new

weixin_47366919的博客 4203

面试中常考的数学题——截木棍、圆上取点、赛马、红蓝墨水,测试毒药、坐到正确座位问题

文章目录1.将一根木棒截成三段,问能够组成三角形的概率;2.在圆上任取三点,问能够组成锐角、直角、钝角三角形的概率;3.共有25匹马,找出最快的3匹,只有5个赛道,每次比赛只能得到5匹马的速度排序,最少需要多少次比赛;4 有两瓶红蓝墨水,体积一样,现在从红墨水中舀一勺加入蓝墨水中,搅拌均匀后,在从蓝墨水中舀一勺加到红墨水中,试问这两瓶墨水哪瓶纯度更高。 1.将一根木棒截成三段,问能够组成三角形的概率; 来源:https://blog.youkuaiyun.com/weixin_41245919/article/deta

weixin_41558411的博客 4904

mabl:AI原生测试自动化平台的基础使用

mabl是一个基于人工智能和机器学习的云原生测试自动化平台。它通过使用先进的技术,如机器学习,自动创建和执行测试,自动分析测试结果,并根据需求的变化自动适配和维护测试。这样的自动化过程极大地提高了软件测试的效率和准确性。mabl的口号是 “You write code, mabl tests”,意味着开发者只需关注编写代码,而测试工作则可以交给mabl来完成。mabl的平台支持多种测试类型,包括 Web、App、Api、可访问性和性能测试,使得团队能够更快速、更有信心地发布软件。

blues_C的博客 3655

使用DelayQueue 分布式延时队列,干掉定时任务!

DelayQueue 是 Java 并发包 (java.util.concurrent) 中的一个无界阻塞队列,用于存放实现了 Delayed 接口的元素。只有当元素的延迟时间到期时,才能从队列中取出该元素。这个方案可以有效替代传统的定时任务轮询方式,提供更高效、更精确的延时处理能力。高性能:基于内存的DelayQueue,处理速度快。分布式支持:通过Redis持久化,支持多实例部署。替代定时任务:不再需要轮询数据库,减少系统压力。精确延时:消息在精确的时间点被处理。可扩展:支持多种业务场景,易于扩展。

曼陀罗的博客 298

备战2025数学建模国赛(算法46):多目标优化

本篇博客将深入浅出地介绍多目标优化的核心概念、主流算法,并重点结合一个数学建模竞赛的经典案例,提供完整的Python代码实现,助你在未来的竞赛中游刃有余。它通过寻找帕累托最优解集,完美地诠释了“鱼与熊掌不可兼得”的权衡思想,为最终决策提供科学依据。这些问题都包含多个相互冲突的目标,传统的单目标优化方法(如梯度下降、单纯形法)对此无能为力,因为它们无法同时优化多个目标。在数学建模竞赛中,我们面临的绝大多数问题都不是单一的“最好”,而是充满权衡与妥协的“最优”。记住,成功的建模不仅在于解出问题,更在于清晰地。

YOLO 283

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

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

weixin_44626952的博客 3565

基于扩散模型的图像去噪与修复:原理、实现与性能分析【附核心代码】

扩散模型(Diffusion Models)在图像修复、去噪、风格化、超分辨率等领域的应用,展示了其强大的生成能力和灵活性。通过模拟图像逐步加噪声再去噪的过程,扩散模型不仅能够恢复图像的细节,还能生成高质量的图像。本文详细探讨了扩散模型在图像修复和增强中的应用,并通过具体代码示例展示了如何使用扩散模型进行去噪、风格化、图像超分辨率等任务。扩散模型在图像修复中通过逐步去噪修复损坏的区域,在图像去噪中则能够去除图像中的噪声并保留细节;在图像风格化中,扩散模型通过结合目标风格和内容生成富有艺术性的图像;

一键难忘的博客 2928

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

SpringBoot 异步延时任务

这个方法会在Spring容器启动后,所有Bean都已经被创建和初始化之后被调用。这个方法的参数是一个字符串数组,通常包含命令行参数,但是你可以根据需要忽略这个参数。在 run 方法中启用线程循环从队列中获取数据,获取不到就阻塞线程,直到有数据为止。异步延时任务在日常工作中是比较常见的。定义一个静态变量DelayQueue,用于保存延时任务。延迟队列是 jdk1.5 提供的,核心是优先级队列。要求队列中的元素必须实现。

MichaelZ的博客 1579

VB摄像头监控

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

springboot使用RabbitMQ实现延时任务

延时队列顾名思义,即放置在该队列里面的消息是不需要立即消费的,而是等待一段时间之后取出消费。那么,为什么需要延迟消费呢?我们来看以下的场景 订单业务: 在电商/点餐中,都有下单后 30 分钟内没有付款,就自动取消订单。短信通知: 下单成功后 60s 之后给用户发送短信通知。失败重试: 业务操作失败后,间隔一定的时间进行失败重试。 本文基于springboot,使用rabbitmq_delaye...

weixin_30496751的博客 237

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

springboot+rabbitmq实现延时任务

springboot+rabbitmq实现延时任务rabbitmq部署springboot集成 rabbitmq部署 这里采用了docker直接部署 1、拉取镜像 docker pull rabbitmq:management 2、启动镜像 docker run -dit --name Myrabbitmq -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin -p 15672:15672 -p 5672:5672 rabbitmq:m

溯夜Alex的博客 753

SpringBoot DelayQueue实现延时队列

亲测有效、你们也可直接复制下面代码先测试一遍是否可行,然后在根据自己业务进行修改一、Delayed二、DelayTask三、TaskBase四、DelayQueueManager五、测试效果 一、Delayed package com.front.Queue; import java.util.concurrent.TimeUnit; /** * @author LunarYouI * @create 2021-09-24 10:31 */ public interface Delayed ext

qq_46100517的博客 1781

任务系统源码java_延时任务机制

/*** 延时任务生产 rabbitmq实现**@authorChopper*@versionv1.0* @Description: 原理:利用amqp的死信队列的超时属性,将超时的任务转到普通队列交给消费者执行。* 添加任务,将任务执行标识、beanid、执行时间,hash值存入redis,标识任务需要执行* 任务编辑,将之前的标识删除,重新添加任务* 添加删除,删除redis中的任务标识,消费...

weixin_27330481的博客 177

Rabbitmq 实现延时任务

1、需要用到插件 rabbitmq_delayed_message_exchange 来实现,插件下载地址:https://www.rabbitmq.com/community-plugins.html 2、下载后把插件放到plugins 里面,然后到 sbin里面打开cmd,执行rabbitmq-plugins enable rabbitmq_delayed_m...

weixin_30673611的博客 177

SpringBoot RabbitMQ 延时队列取消订单【SpringBoot系列14】

SpringCloud 大型系列课程正在制作中,欢迎大家关注与提意见

代码小疯子 1840

5.Springboot2.x集成Rabbitmq实现延时消费

Springboot2.x集成Rabbitmq实现延时消费 前言 比如我们在使用mq的时候并不希望立即收到消息,比如实现3分钟后再查询订单,这时候我们就需要使用延迟消息发送了。 RabbitMQ如何实现迟队列? AMQP协议和RabbitMQ队列本身没有直接支持延迟队列功能。但是我们可以通过RabbitMQ的两个特性来曲线实现延迟队列: 特性1、Time To Live(TTL) 1.Rabbit...

霓虹深处 974

Springboot集成RabbitMQ的延时队列

Springboot集成RabbitMQ的延时队列一、延时队列二.下载并且安装erlang和RabbitMQ三.代码实现3.1.新增依赖3.2.修改application.yml3.3.配置队列3.4 发送消息3.5 消费消息3.6 测试队列3.7 测试结果 一、延时队列 延时队列的使用场景:1.未按时支付的订单,30分钟过期之后取消订单;2.给活跃度比较低的用户间隔N天之后推送消息,提高活跃度;...

qq_44051354的博客 233

springboot使用RabbitMQ实现延时

springboot使用RabbitMQ实现延时 application.properties spring.rabbitmq.username=guest spring.rabbitmq.password=guest spring.rabbitmq.host=localhost spring.rabbitmq.port=5672 spring.rabbitmq.virtual-host=test...

luojiancc1的博客 301
上一篇: fabric 智能合约开发详解
下一篇: 区块链之超级账本Fabric 基于SDK应用开发
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值