订单延迟关闭之delayQueue解决方案

一. 知识要点

  1. delayQueue相关api
  2. 线程池知识点
  3. spring异步注解@Async配置和使用

二. 主要代码

  1. 订单类
public class Message implements Delayed {

    /** 创建时间 10分钟以后, 测试可以降低该值 */
    private static final int SECOND_NUM = 600;

	/**订单id*/
    private int id;
    /**订单状态*/
    private String state;
    /**订单创建时间*/
    private Date createTime;


    public Message(int id, String state, Date createTime) {
        this.id = id;
        this.state = state;
        this.createTime = createTime;
    }

    public int getId() {
        return id;
    }

    public String getState() {
        return state;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setState(String state) {
        this.state = state;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

	/**
	 *获取订单过期时间
	 */
    private Date getCancelTime(Date createTime) {
        return Date.from(createTime.toInstant().plusSeconds(SECOND_NUM));
    }

	/**
	 * 判断元素是否过期(小于等于0时过期)
	 *
	 */
    @Override
    public long getDelay(TimeUnit unit) {
        return unit.convert(getCancelTime(createTime).getTime() - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
    }

    @Override
    public String toString() {
        return "Message{" +
                "id=" + id +
                ", state='" + state + '\'' +
                ", createTime=" + createTime +
                '}';
    }

	/**
	 * 根据元素过期时间排序, 哪个元素最早到过期时间, 就排在前面 
	 *
	 */
    @Override
    public int compareTo(Delayed o) {
        Message msg = (Message) o;
        return Long.compare(this.createTime.getTime(), msg.getCreateTime().getTime());
    }
}
  1. sping配置线程池(数据仅供参考, 根据实际业务配置参数和拒绝策略)


  1. 业务层主要代码(异步方法)
	@Async
    @Override
    public void delayClose(Message msg) {
        // 初始化delayQueue(如果之前有过期未处理的订单, 可以放在这里)
        List unpaidOrder = orderMapper.getOvertimeAndUnpaidOrder();
       DelayQueue queue = new DelayQueue<>();
       if (!unpaidOrder.isEmpty()) {
            queue.addAll(unpaidOrder);
        }
        // 将最近的一条订单添加进去
        queue.add(msg);
        while (!queue.isEmpty()) {
            // 关闭未支付的订单
            cancelOrder(queue);
        }
    }

	private void cancelOrder(DelayQueue queue) {
        try {
            Message msg = queue.take();
            // 判断支付状态
            if ("unpaid".equarls(msg.state)) {
                // 修改订单状态
            }
        } catch (InterruptedException e) {
           logger.error(e.getMessage(), e);
        }
    }

你可能感兴趣的:(工具类)