Springboot使用DelayQueue實現訂單自動取消


DelayQueue小結

  • DelayQueue是一個有序的無界BlockingQueue,用於放置實現了Delayed接口的對象,其中的對象在到期時才能從隊列中取走。
  • DelayQueue只能添加實現了Delayed接口的對象,不能將null元素放置到這種隊列中。

BlockingQueue中add,offer,put方法區別

  • add
    將指定的元素插入到此隊列中,在成功時返回 true,如果當前沒有可用空間,則拋出 IllegalStateException,該方式為非阻塞添加。
  • offer
    將指定元素插入到此隊列的尾部(如果立即可行且不會超出此隊列的容量),在成功時返回 true,如果此隊列已滿,則返回 false,此方法通常要優於 add 方法,該方式為非阻塞添加。
  • put
    將指定元素插入到此隊列的尾部,該方式為阻塞添加,則等待空間變得可用。

代碼實現

初始化一個延遲隊列DelayQueue

/**
 * 定義一個延遲隊列
 *
 * @author zengwei
 * @email 1014483974@qq.com
 */
public volatile static DelayQueue<Orders> orderQueue = new DelayQueue();

在訂單類中,實現Delayed接口

/**
 * 訂單實體類
 *
 * @author zengwei
 * @email 1014483974@qq.com
 */
@Entity
@Data
@Builder(toBuilder = true)
@EqualsAndHashCode(callSuper = false)
public class Orders implements Delayed {

	@ApiModelProperty(value = "訂單編號")
    private String orderNumber;

    @ApiModelProperty(value = "訂單自動關閉時間,DelayQueue使用")
    private Date time;

    @Override
    public long getDelay(TimeUnit unit) {
        return unit.convert(time.getTime() - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
    }

    @Override
    public int compareTo(Delayed o) {
        return time.compareTo(((Orders) o).getTime());
    }

}

能日賺30手賺試玩平台,親測有效

定義一個Job類,實現CommandLineRunner接口,用於在項目啟動后執行該任務,通過take()方法從隊列中獲取到指定對象出列,在執行完任務后,調用remove()方法從隊列刪除該任務

/**
 * 延遲隊列自動取消訂單
 * 
 * 【能日賺30手賺試玩平台,推薦使用iphone操作】 
 * 【https://mp.weixin.qq.com/s?__biz=MzIyODgxNjkyOQ==&mid=100000040&idx=1&sn=47c0245f9dbe70f3ad6b2540209af2c2&chksm=684d60665f3ae97095ba07d8c6804bac4f55dbc6e7100fbb233945f65364df88682d41332eb7&xtrack=1&scene=0&subscene=10000&clicktime=1616647421&enterid=1616647421&ascene=7&devicetype=android-29&version=28000165&nettype=WIFI&abtest_cookie=AAACAA%3D%3D&lang=zh_CN&exportkey=AdxLWFyJlgtM6uFZCpgWtBk%3D&pass_ticket=G8rEeGdox4FPpICRkrKy6ho2QZozCzXi%2Be7gV5bXnQaXoZK2pw4S8Wf2j%2Bt3D8mi&wx_header=1】
 *
 * @author zengwei
 * @email 1014483974@qq.com
 */
@Slf4j
@Component
public class OrderDelayQueueJob implements CommandLineRunner {

    public void orderTask() {
        log.info("開啟自動取消訂單job,當前時間 = {}", new DateTime().toString());
        while (true) {
            try {
            	// 獲取指定訂單信息
                Orders order = DelayQueueConfig.orderQueue.take();
                // 從隊列中刪除該數據
                DelayQueueConfig.orderQueue.remove(order);
                log.info("訂單" + order.getOrderNumber() + "超時取消,取消時間 = {}", new DateTime().toString());
                log.info("Initial Size = {}", DelayQueueConfig.orderQueue.size());
            } catch (InterruptedException e) {
                break;
            }
        }
    }

    @Override
    public void run(String... args) {
        // 自動取消訂單開啟
        ThreadUtil.execute(this::orderTask);
    }
}

在創建訂單的位置,如買家未付款,則將該訂單加入DelayQueue延遲隊列,指定30s后自動取消訂單

/**
 * 將訂單加入延遲隊列,30s后自動取消
 * 
 * 【能日賺30手賺試玩平台,推薦使用iphone操作】 
 * 【https://mp.weixin.qq.com/s?__biz=MzIyODgxNjkyOQ==&mid=100000040&idx=1&sn=47c0245f9dbe70f3ad6b2540209af2c2&chksm=684d60665f3ae97095ba07d8c6804bac4f55dbc6e7100fbb233945f65364df88682d41332eb7&xtrack=1&scene=0&subscene=10000&clicktime=1616647421&enterid=1616647421&ascene=7&devicetype=android-29&version=28000165&nettype=WIFI&abtest_cookie=AAACAA%3D%3D&lang=zh_CN&exportkey=AdxLWFyJlgtM6uFZCpgWtBk%3D&pass_ticket=G8rEeGdox4FPpICRkrKy6ho2QZozCzXi%2Be7gV5bXnQaXoZK2pw4S8Wf2j%2Bt3D8mi&wx_header=1】
 * 
 * @author zengwei
 * @email 1014483974@qq.com
 */
Orders orders = Orders.builder()
        .orderNumber(RandomUtil.randomNumbers(10))
        .time(DateUtil.offset(new Date(), DateField.SECOND, 30))
        .build();
DelayQueueConfig.orderQueue.add(orders);
log.info("訂單" + orders.getOrderNumber() + "未付款,到期時間 = {}",DateUtil.formatDateTime(orders.getTime()));

能日賺30手賺試玩平台,親測有效

運行程序后創建待支付訂單,30s后該訂單自動取消,同時從隊列中刪除,日志中Initial Size = 0,代表隊列的長度
在這里插入圖片描述
在重啟服務器后,那些未執行的延遲任務就不存在了,目前我是在項目重啟時,定義一個@Component組件,異步去查詢未付款的訂單,如果已超時,則直接改為已取消;未超時的訂單,則加入DelayQueue延遲隊列中,持久化方案目前仍在學習中。

未經允許,禁止轉載

Creative Commons License
This work is licensed under a Creative Commons Attribution 4.0 International License.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM