Java延时队列取消未支付的订单 之 重启服务任务丢失

一、定义延迟任务类

java 复制代码
package com.activity.domain;

import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

/**
 * 延迟任务类
 */
public class DelayedCancellation implements Delayed {
    private String order;
    private final long delayTime; // 延迟时间

    public DelayedCancellation(String order, long delayTime) {
        this.order = order;
        this.delayTime = System.currentTimeMillis() + delayTime;
    }

    public String getOrder() {
        return order;
    }

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

    @Override
    public int compareTo(Delayed o) {
        return Long.compare(this.delayTime, ((DelayedCancellation) o).delayTime);
    }
}

二、执行任务

java 复制代码
package com.activity.utils;

import java.util.concurrent.DelayQueue;

import com.zaiyun.activity.domain.DelayedCancellation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CancellationManager {
    private static final Logger wechatLogger = LoggerFactory.getLogger("extend-wechat");
    private final DelayQueue<DelayedCancellation> delayQueue = new DelayQueue<>();

    public void scheduleOrderCancellation(String order, long delayTime) {
        DelayedCancellation delayedOrderCancellation = new DelayedCancellation(order, delayTime);
        delayQueue.put(delayedOrderCancellation);
    }

    public void startOrderCancellationScheduler() {
        new Thread(() -> {
            while (true) {
                try {
                    DelayedCancellation delayedOrderCancellation = delayQueue.take();
                    processOrderCancellation(delayedOrderCancellation.getOrder());
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }).start();
    }

    /**
     * 执行取消操作
     * @param order
     */
    private void processOrderCancellation(String order) {
        wechatLogger.info("执行取消任务-订单编号:" + order);
    }
}

三、触发使用

java 复制代码
/**
     * 30分钟未支付将取消参与
     */
    public static void cancelParticipation(String order) {
        CancellationManager cancellationManager = new CancellationManager();
        cancellationManager.startOrderCancellationScheduler();
        cancellationManager.scheduleOrderCancellation(order, TimeUnit.MINUTES.toMillis(30));
        wechatLogger.info("触发延时队列-订单编号:" + order);
    }

四、执行日志

五、服务重启问题

在调试的过程中发现一个严重的问题 (重启服务后任务丢失了

因为延迟队列没有做持久化,那么服务重启之后,原来在队列的任务就丢失啦。所以,服务重启的时候要去扫描检测订单。

ApplicationRunner执行时机为容器启动完成的时候,实现run方法即可。或使用InitializingBean接口。

java 复制代码
package com.activity.domain;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

/**
 * 初始化执行任务
 */
@Component
public class InitializeTask implements ApplicationRunner {
    private static final Logger wechatLogger = LoggerFactory.getLogger("extend-wechat");
    @Override
    public void run(ApplicationArguments args) {
        wechatLogger.info("初始化执行任务:");
    }
}

本文参考 使用延迟队列处理超时订单

相关推荐
天下无敌笨笨熊1 分钟前
C#视频开发心得
开发语言·c#·音视频
淼澄研学33 分钟前
基于Docker与iptables的AI智能体网络隔离实操指南
开发语言·python
杰哥哥不是个好叔叔40 分钟前
【Spring AI】Spring AI 2.0.1 新特性袭来
java·人工智能·spring
莫陌尛.1 小时前
Java核心知识点:直接内存、CPU密集型线程池、并行流对比文档
java·开发语言
Zane19941 小时前
自定义异常该继承 Exception 还是 RuntimeException,就看这一个问题
java·后端
西峰u1 小时前
Java多线程初阶完整总结|线程、锁、volatile、等待通知、常见案例
java·开发语言·jvm
爱喝可乐的中登1 小时前
SpringBoot 云边协同|智慧地铁 ISCS 改造实战第 10 篇:全网权限与数据隔离重构|线路‑车站‑专业三级 RBAC、边缘数据权限下沉
java·spring boot·重构
夜雨声烦丿1 小时前
从需求到页面:日期计算器应用的 ArkTS 原生实现
开发语言·javascript·华为·harmonyos
落魄实习生1 小时前
Spring AI Alibaba入门-生态集成
java·人工智能·spring
重生之我是Java开发战士1 小时前
【Java EE】认识Linux与项目部署
java·linux·java-ee