DelayedQueue队列

DelayQueue是一个无界的BlockingQueue,用于存储实现了Delayed接口的对象,其中的对象只能在其到期时才能从队列中取走。这种队列是有序的,即队头对象的延迟到期时间最长。注意:不能将null元素放置到这种队列中。
下面先看一个例子:
/**
 * DelayQueue需要存储的对象的类,实现Delayed接口,重写compareTo和getDelay方法
 */
class DelayedQueueEvent implements Delayed {
     private Long startDate;
     
     private String name;
     public DelayedQueueEvent(Long startDate, String name) {
           this.startDate = startDate;
           this.name = name;
     }
     public String getName() {
           return this.name;
     }

     @Override
     public int compareTo(Delayed o) {
           long result = this.getDelay(TimeUnit.NANOSECONDS) - o.getDelay(TimeUnit.NANOSECONDS);
           if (result < 0) {
                return -1;
           } else if (result > 0) {
                return 1;
           }
           return 0;
     }

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

public class DelayedQueueDemo {
     public static void main(String[] args) throws Exception {
           DelayQueue<DelayedQueueEvent> queue = new DelayQueue<>();
           for (int i = 0; i < 10; i++) {
                //startDate启动时间为当前时间延后5秒的整数倍
                DelayedQueueEvent event = new DelayedQueueEvent(System.currentTimeMillis() + (i+1) * 5000, String.valueOf(i));
                queue.add(event);
           }
           System.out.println("当前时间:"+ new Date());
           
           DelayedQueueEvent event;
           while (queue.size() != 0) {
                event = queue.poll();
                if (event != null) {
                     System.out.println("取出" + event.getName() + ":" + new Date());
                }
           }
           
     }
}

运行结果如下:


由结果可知每5秒从 DelayQueue中取出一个元素。
例子很简单,那么有两个问题:
1.添加的元素为什么需要排序呢?
查看源码可知:

private final PriorityQueue<E> q = new PriorityQueue<E>();

public E poll() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            E first = q.peek();
            if (first == null || first.getDelay(TimeUnit.NANOSECONDS) > 0)
                return null;
            else
                return q.poll();
        } finally {
            lock.unlock();
        }
    }
原因是DelayQueue采用了PriorityQueue来存储数据,而PriorityQueue所存储的元素是有序的。
2.compareTo方法应该返回什么样的排序?
此接口的实现必须定义一个 compareTo方法,该方法提供与此接口的 getDelay方法一致的排序
从以上的源码也可以看出,从DelayQueue获取元素时候,是获取PriorityQueue的头元素,并判断是否到达执行的时间,如果没到执行时间,返回null。如果 compareTo提供的排序和getDelay不一致,那么该处就会有问题,就会出现到达执行时间的元素没有被取出。

注意:
getDelay方法返回与此对象相关的剩余延迟时间,以给定的时间单位表示, 查看源码可知DelayQueue给的单位是 纳秒 .

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值