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

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

相关推荐
m0_5719575829 分钟前
Java | Leetcode Java题解之第543题二叉树的直径
java·leetcode·题解
一点媛艺2 小时前
Kotlin函数由易到难
开发语言·python·kotlin
姑苏风2 小时前
《Kotlin实战》-附录
android·开发语言·kotlin
奋斗的小花生3 小时前
c++ 多态性
开发语言·c++
魔道不误砍柴功3 小时前
Java 中如何巧妙应用 Function 让方法复用性更强
java·开发语言·python
NiNg_1_2343 小时前
SpringBoot整合SpringSecurity实现密码加密解密、登录认证退出功能
java·spring boot·后端
闲晨3 小时前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
老猿讲编程3 小时前
一个例子来说明Ada语言的实时性支持
开发语言·ada
Chrikk4 小时前
Go-性能调优实战案例
开发语言·后端·golang
幼儿园老大*4 小时前
Go的环境搭建以及GoLand安装教程
开发语言·经验分享·后端·golang·go