使用DelayQueue实现订单限时支付处理

DelayQueue是一个无界阻塞队列,队列中的元素必须实现Delayed接口,在创建元素时可以指定多久才能从队列中获取当前元素。只有在延迟期满时才能从队列中提取元素。

DelayQueue可以用作缓存系统的设计,可以用DelayQueue保存缓存元素的有效期,使用一个线程循环查询DelayQueue,一旦能从DelayQueue中获取元素时,表示缓存有效期到了。

本文使用DelayQueue实现订单限时支付处理,以此加深对DelayQueue的理解。

实现Delayed接口,封装放入DelayQueue中的元素

@Getter
@Setter
@ToString
public class ItemVo<T> implements Delayed {

    //超时时间
    private long expireTime;
    private T data;

    public ItemVo(long expireTime, T data) {
        this.expireTime = expireTime + System.currentTimeMillis();
        this.data = data;
    }

    //用于获取到期剩余时间
    public long getDelay(TimeUnit unit) {
        long d = unit.convert(this.expireTime
                - System.currentTimeMillis(), unit);
        return d;
    }

    //按照剩余时间排序
    public int compareTo(Delayed o) {
        long d = (getDelay(TimeUnit.MILLISECONDS)
                - o.getDelay(TimeUnit.MILLISECONDS));
        if (d == 0) {
            return 0;
        } else {
            if (d < 0) {
                return -1;
            } else {
                return 1;
            }
        }
    }

}

订单实体

@Getter
@Setter
@ToString
public class OrderEntity {

    //订单金额
    private double orderAmount;

    //订单号
    private String orderNo;

    //0:未支付,1:已支付
    private int orderStatus;

    public OrderEntity(String orderNo, double orderAmount, int orderStatus) {
        this.orderAmount = orderAmount;
        this.orderNo = orderNo;
        this.orderStatus = orderStatus;
    }

}

启动三个线程,分别模拟生成订单、支付订单、处理订单超时

public class DelayOrder {
    public static void main(String[] args) {
        DelayQueue<ItemVo<OrderEntity>> delayQueue = new DelayQueue<>();

        Map<String, OrderEntity> map = new ConcurrentHashMap<>();

        //生成订单线程
        new Thread(() -> {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            //模拟订单号
            long orderNo = 20200101000L;
            while (true) {
                try {
                    //随机等待一个时间后,再模拟生成一个订单
                    Thread.sleep(new Random().nextInt(10) * 1000);

                    //生成订单
                    OrderEntity orderEntity = new OrderEntity(String.valueOf(orderNo), new Random().nextInt(1000), 0);

                    //设置订单生成后10秒内未支付就超时。
                    ItemVo<OrderEntity> itemVo = new ItemVo<>(10 * 1000, orderEntity);

                    Date date = new Date();
                    date.setTime(itemVo.getExpireTime());

                    System.out.println("当前系统时间:" + simpleDateFormat.format(new Date()) +
                            ", 生成一个订单,订单号:" + orderEntity.getOrderNo() +
                            ", 订单金额:" + orderEntity.getOrderAmount() +
                            ", 订单支付到期时间:" + simpleDateFormat.format(date));

                    //所有订单放入一个map容器中
                    map.put(String.valueOf(orderNo), orderEntity);

                    //订单号递增
                    orderNo++;

                    //放入延时队列
                    delayQueue.offer(itemVo);

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

        //模拟已经支付的订单
        new Thread(() -> {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            while (true) {
                try {
                    //随机等待一个时间后,再支付订单
                    Thread.sleep(new Random().nextInt(15) * 1000);
                    String orderNo = "";

                    Iterator<Map.Entry<String, OrderEntity>> iterator = map.entrySet().iterator();
                    if (iterator.hasNext()) {
                        OrderEntity orderEntity = iterator.next().getValue();
                        //设置订单状态为已支付
                        orderEntity.setOrderStatus(1);
                        orderNo = orderEntity.getOrderNo();
                        System.out.println("当前系统时间:" + simpleDateFormat.format(new Date()) + ", 有订单已经支付成功,订单号:" + orderNo +
                                ", 订单金额:" + orderEntity.getOrderAmount());
                    }

                    //处理完从map中移除
                    map.remove(orderNo);

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();


        //处理超时订单线程
        new Thread(() -> {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            while (true) {
                try {
                    //到期后从队列中取出
                    ItemVo<OrderEntity> itemVo = delayQueue.take();
                    Date date = new Date();
                    date.setTime(itemVo.getExpireTime());

                    OrderEntity orderEntity = itemVo.getData();

                    //处理超时未支付订单
                    if (orderEntity.getOrderStatus() == 0) {
                        System.out.println("有超时未支付的订单,订单号:" + orderEntity.getOrderNo() +
                                ", 订单金额:" + orderEntity.getOrderAmount() +
                                ", 订单支付到期时间:" + simpleDateFormat.format(date));
                    }

                    //处理完从map中移除
                    map.remove(orderEntity.getOrderNo());

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

执行结果:
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码拉松

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值