訂單延遲關閉之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配置線程池(數據僅供參考, 根據實際業務配置參數和拒絕策略)
<task:annotation-driven executor="asyncExecutor"/>
<task:executor id="asyncExecutor" pool-size="10-50" queue-capacity="500" keep-alive="200" rejection-policy="CALLER_RUNS"/>
  1. 業務層主要代碼(異步方法)
	@Async
    @Override
    public void delayClose(Message msg) {
        // 初始化delayQueue(如果之前有過期未處理的訂單, 可以放在這裏)
        List<Message > unpaidOrder = orderMapper.getOvertimeAndUnpaidOrder();
       DelayQueue<Message > queue = new DelayQueue<>();
       if (!unpaidOrder.isEmpty()) {
            queue.addAll(unpaidOrder);
        }
        // 將最近的一條訂單添加進去
        queue.add(msg);
        while (!queue.isEmpty()) {
            // 關閉未支付的訂單
            cancelOrder(queue);
        }
    }

	private void cancelOrder(DelayQueue<Message > queue) {
        try {
            Message msg = queue.take();
            // 判斷支付狀態
            if ("unpaid".equarls(msg.state)) {
                // 修改訂單狀態
            }
        } catch (InterruptedException e) {
           logger.error(e.getMessage(), e);
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章