您好,欢迎来到12图资源库!分享精神,快乐你我!我们只是素材的搬运工!!
  • 首 页
  • 当前位置:首页 > 开发 > WEB开发 >
    面试侃集合 | DelayQueue篇
    时间:2021-08-07 21:26 来源:网络整理 作者:网络 浏览:收藏 挑错 推荐 打印

    面试侃集合 | DelayQueue篇

    面试官:良久不见啊,上次我们聊完了PriorityBlockingQueue,明天我们再来聊聊和它相关的DelayQueue吧?

    Hydra:就知道你前面一定给我挖了坑,DelayQueue也是一个无界阻塞队列,但是和之前我们聊的其他队列不同,不是一切类型的元素都可以放出来,只要完成了Delayed接口的对象才能放进队列。Delayed对象具有一个过时时间,只要在抵达这个到期时间后才能从队列中取出。

    面试官:有点意思,那么它有什么运用场景呢?

    Hydra:不得不说,由于DelayQueue的精妙设计,运用场景还是蛮多的。例如在电商系统中,假设有一笔订单在下单30分钟内没有完成支付,那么就需求自动取消这笔订单。还有,假设我们缓存了一些数据,并希望这些缓存在一定时间后失效的话,也可以运用延迟队列将它从缓存中删除。

    以电商系统为例,可以复杂看一下这个流程:

    面试侃集合 | DelayQueue篇

    面试官:看起来和义务调度有点相似啊,它们之间有什么区别吗?

    Hydra:义务调度更多的倾向于定时的特性,是在指定的时间点或时间距离执行特定的义务,而延迟队列更多倾向于在指定的延迟时间后执行义务。相对义务调度来说,下面举的例子中的延迟队列场景都具有高频率的特性,运用定时义务来完成它们的话会显得有些过于笨重了。

    面试官:好了,你也白话了半天了,能入手就别吵吵,还是先给我写个例子吧。

    Hydra:好嘞,前面说过存入队列的元素要完成Delayed接口,所以我们先定义这么一个类:

    public class Task implements Delayed { 

        private String name

        private long delay,expire; 

        public Task(String name, long delay) { 

            this.name = name

            this.delay = delay; 

            this.expire=System.currentTimeMillis()+delay; 

        } 

     

        @Override 

        public long getDelay(TimeUnit unit) { 

            return unit.convert(this.expire - System.currentTimeMillis(), TimeUnit.MILLISECONDS); 

        } 

        @Override 

        public int compareTo(Delayed o) { 

            return (int)(this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS)); 

        } 

     

    完成了Delayed接口的类必需要完成下面的两个办法:

    getDelay办法用于计算对象的剩余延迟时间,判别对象能否到期,计算办法普通运用过时时间减以后时间。假设是0或正数,表示延迟时间曾经用完,否则阐明还没有到期

    compareTo办法用于延迟队列的外部排序比较,这里运用以后对象的延迟时间减去被比较对象的延迟时间

    在完成队列中元素的定义后,向队列中参加5个不同延迟时间的对象,并等候从队列中取出:

    public void delay() throws InterruptedException { 

        DelayQueue<Task> queue=new DelayQueue<>(); 

        queue.offer(new Task("task1",5000)); 

        queue.offer(new Task("task2",1000)); 

        queue.offer(new Task("task3",6000)); 

        queue.offer(new Task("task4",100)); 

        queue.offer(new Task("task5",3000)); 

     

        while(true){ 

            Task task = queue.take(); 

            System.out.println(task); 

        } 

    运转结果如下,可以看到按照延迟时间从短到长的顺序,元素被依次从队列中取出。

    Task{name='task4', delay=100} 

    Task{name='task2', delay=1000} 

    Task{name='task5', delay=3000} 

    Task{name='task1', delay=5000} 

    Task{name='task3', delay=6000} 

    面试官:看起来运用还是挺复杂的,但明天也不能这么草草了事吧,还是说说原理吧。

    (责任编辑:admin)