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

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

相关推荐
卷到起飞的数分38 分钟前
JVM探究
java·服务器·jvm
Geek攻城猫39 分钟前
Java生产环境问题排查实战指南
java·jvm
t***5448 小时前
Clang 编译器在 Orwell Dev-C++ 中的局限性
开发语言·c++
OtIo TALL8 小时前
redis7 for windows的安装教程
java
oy_mail8 小时前
QoS质量配置
开发语言·智能路由器·php
oyzz1209 小时前
PHP操作redis
开发语言·redis·php
uNke DEPH9 小时前
Spring Boot的项目结构
java·spring boot·后端
nashane9 小时前
HarmonyOS 6学习:网络能力变化监听与智能提示——告别流量偷跑,打造贴心网络感知应用
开发语言·php·harmony app
xixingzhe29 小时前
idea启动vue项目
java·vue.js·intellij-idea
wzl202612139 小时前
企业微信定时群发技术实现与实操指南(原生接口+工具落地)
java·运维·前端·企业微信