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("初始化执行任务:");
    }
}

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

相关推荐
兆子龙11 小时前
ahooks useRequest 深度解析:一个 Hook 搞定所有请求
java·javascript
兆子龙11 小时前
React Suspense 从入门到实战:让异步加载更优雅
java·javascript
咕白m62514 小时前
Java 实现 Excel 转 HTML:完整示例
java
RealPluto14 小时前
Spring AOP 失效排查
java·spring
码路飞15 小时前
热榜全是 OpenClaw,但我用 50 行 Python 就造了个桌面 AI Agent 🤖
java·javascript
Nyarlathotep011315 小时前
LinkedList源码分析
java·后端
用户83071968408215 小时前
Java 告别繁琐数据统计代码!MySQL 8 窗口函数真香
java·sql·mysql
带刺的坐椅16 小时前
SolonCode v0.0.20 发布 - 编程智能体(新增子代理和浏览器能力)
java·ai·agent·solon·solon-ai·claude-code·openclaw
会员源码网17 小时前
数字格式化陷阱:如何优雅处理 NumberFormatException
java