zoukankan      html  css  js  c++  java
  • 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.

  • 相关阅读:
    物料清单概述
    java开发webservice的1种方式
    java web service简单示例
    IOS证书过期
    Windows 2012 R2 安装net4.6.1
    sqlserver 性能调优脚本
    solidty--owner.sol
    ERC20-USDT
    EOS 公开节点及自有节点部署
    微信第三方平台授权流程
  • 原文地址:https://www.cnblogs.com/shiqiboy3974/p/14748593.html
Copyright © 2011-2022 走看看