DelayQueue 浅谈理解

  DelayQueue是一个无界的BlockingQueue,用于放置实现了Delayed接口的对象,其中的对象只能在其到期时才能从队列中取走。这种队列是有序的,即队头对象的延迟到期时间最长。注意:不能将null元素放置到这种队列中。

加入其中的元素必需实现Delayed接口。当生产者线程调用put之类的方法加入元素时,会触发Delayed接口中的compareTo方法进行排序,也就是说队列中元素的顺序是按到期时间排序的,而非它们进入队列的顺序。排在队列头部的元素是最早到期的,越往后到期时间赿晚。

直接上代码:

首先定义业务类:

class Order implements Delayed {
        private long time;
        String name;

        public Order(String name, long time) {
            this.name = name;
            // 如果需要修改时间格式   此处对定义的时间自行约定转化即可 此处定义秒
            this.time = TimeUnit.SECONDS.toMillis(time) + System.currentTimeMillis();
        }

        @Override
        public long getDelay(TimeUnit unit) {
            long diffTime = time - System.currentTimeMillis();
            return diffTime;
        }

        @Override
        public int compareTo(Delayed o) {
            Order item = (Order) o;
            long diff = this.time - item.time;
            return diff >= 0 ? 1 : -1;
        }

        public String getName() {
            return name;
        }
    }

定义一个Order类,关键字段时间,name可以在实际业务中定义为你需要适用的数据实体,OBJ也可。实现Delayed,getDelay用于校验当前时间是否超过设定时间,compareTo会对超过时间的元素进行排序,他的排序方式需要定义为getDelay一致。

接下来我们上测试代码:

public static void main(String[] args) throws InterruptedException {
        //实际业务中 对于延迟任务来说,一把会放在线程池中自行处理  因此提前设置
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        // 此处定义秒
        Order order1 = new Order("order1", 1);
        Order order2 = new Order("order2", 5);
        Order order3 = new Order("order3", 3);
        DelayQueue<Order> queue = new DelayQueue<>();
        queue.put(order1);
        queue.put(order2);
        queue.put(order3);
        System.out.println("开始时间   当前时间:" + LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
        Callable<Integer> task;
        task = new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                for (; ; ) {
                    if (CollectionUtils.isEmpty(queue)) {
                        break;
                    }
                    Order take = queue.take();
                    if (take == null) {
                        break;
                    }
                    System.out.println(take.getName()+"    当前时间:" + LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
                }
                return 1;
            }
        };
        List<Callable<Integer>> tasks = new ArrayList<>();
        tasks.add(task);
        //提交任务 并关闭线程
        executorService.invokeAll(tasks);
        executorService.shutdown();
    }

执行结果:

开始时间   当前时间:2021-09-07T11:18:58.568
order1    当前时间:2021-09-07T11:18:59.486
order3    当前时间:2021-09-07T11:19:01.486
order2    当前时间:2021-09-07T11:19:03.486

如果需要改为毫秒级别计算的话,构造器中不要转化即可。

但是如果是单体项目,建议将数据持久化,并且开线程处理,因为该队列使用内存存储,如果一旦出现异常,比如宕机,name存储的重要数据将会小时,实际业务中,会使用到MQ或者Redis进行处理,用于避免重要数据的丢失。

个人见解,不喜勿喷!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值