延迟队列实现30分钟订单自动过期失效

延迟队列实现30分钟订单自动过期失效

  • 1.首先Order实体类得实现Delayed接口
  • 2.创建延迟服务类
  • 3.使用

有一天,公司项目需求让用户订单未支付超过30分钟,自动取消订单状态.
我仔细想想用定时器?每分钟跑一下?显然不够优雅.
旁边同事看到我焦头烂额,有没有任何思绪.
突然扔给我两个文件,即高效又优雅的解决了我的问题,
我如获至宝,现在分享给大家.

1.首先Order实体类得实现Delayed接口

public class TjOrder implements Delayed, Serializable {
    // ....省略好多字段
    
    /**
     * 传入进来排序的实例
     */
    @Override
    public int compareTo(Delayed o) {
        if (this == o) {
            return 0;
        }
        TjOrder order= (TjOrder) o;
        long time = this.createTime.getTime() - order.getCreateTime().getTime();
        return time == 0 ? 0 : time < 0 ? -1 : 1;
    }

    /**
     * 取出处理过期订单
     */
    @Override
    public long getDelay(TimeUnit unit) {
        // ORDER_TIME_OUT = 1800000L
        return (this.createTime.getTime() + ConstantsUtil.ORDER_TIME_OUT) - System.currentTimeMillis();
    }

    /**
     * 重写用于删除
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        TjOrder other = (TjOrder) obj;
        if (other.getOrderNo() == null) {
            return false;
        } else if (!id.equals(other.getId())) {
            return false;
        } else if (!orderNo.equals(other.getOrderNo())) {
            return false;
        }
        return true;
    }
}

2.创建延迟服务类

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;

@Service
public class DelayService implements InitializingBean {

    Logger logger = LoggerFactory.getLogger(this.getClass());
    private static DelayQueue<TjOrder> delayQueue = new DelayQueue<TjOrder>();
    private static AtomicBoolean start = new AtomicBoolean(false);
    // 线程池
    private static ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("useragent-pool-%d").build();
    private static ExecutorService executorService = new ThreadPoolExecutor(
            3, // 核心线程池大小
            6, // 最大线程池大小
            60L, // 线程最大空闲时间
            TimeUnit.MILLISECONDS, // 时间单位(毫秒)
            new LinkedBlockingQueue<Runnable>(),  // 线程等待队列
            threadFactory, // 线程创建工厂
            new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
    );


    @Autowired
    private TjOrderService tjOrderService;

    @Override
    public void afterPropertiesSet() throws Exception {
        start();
    }

    public <T> void start() {
        if (start.get()) {
            return;
        }
        start.set(true);

        //放入待付款订单
        TjOrder order = new TjOrder();
        // -1 未支付,常量池状态
        order.setState(ConstantsUtil.ORDER_STATE_CREATE);
        List<TjOrder> list = tjOrderService.getList(order);
        list.forEach(item -> delayQueue.add(item));

        executorService.submit(() -> {
            // 取消订单
            while (start.get()) {
                try {
                    TjOrder order = delayQueue.take();
                    if (order != null) {
                        // 订单过期
                        TjOrder updateOrder = new TjOrder();
                        updateOrder.setId(order.getId());
                        // 常量池取消状态
                        updateOrder.setState(ConstantsUtil.ORDER_STATE_CANCEL);
                        tjOrderService.update(updateOrder);
                        // 还原
                        logger.info("=======订单号为[" + order.getOrderNo() + "]未支付过期,过期时间为:" + DateUtil.getNowStringTime() + "=======");
                    }
                } catch (Exception e) {

                }
            }
        });
    }

    public void add(TjOrder order) {
        logger.info("加入订单队列订单号===={}", order.getOrderNo());
        if (!start.get()) {
            throw new RuntimeException("订单服务还未启动");
        }
        delayQueue.add(order);
    }

    public void delete(TjOrder order) {
        if (!start.get()) {
            throw new RuntimeException("订单服务还未启动");
        }
        delayQueue.remove(order);
    }

    public int getSize() {
        if (!start.get()) {
            throw new RuntimeException("订单服务还未启动");
        }
        return delayQueue.size();
    }

}

3.使用

// 放入延迟队列
DelayService delayService = new DelayService();
delayService.add(order);

你可能感兴趣的:(常见问题,浩哥的JAVA之路)