您的位置 首页 java

java并发之DelayQueue类的介绍和使用

DelayQueue简介

DelayQueue 并发队列是一个无界阻塞延迟队列,队列中的每个元素都有个过期时间, 当从队列获取元素时,只有过期元素才会出队列。队列头元素是最快要过期的元素。,其内部使用 PriorityQueue 存放数据,使用 ReentrantLock 实现线程同步。队列里面的元素要实现 Delayed 接口,其中一个是获取当前元素到过期时间剩余时间的接口,在出队时判断元素是否过期了,一个是元素之间比较的接口 ,因为这是一个有优先级的队列。注意:不能将null元素放置到这种队列中。

主要的方法介绍

§ offer(E e)

插入元素到队列,如果插入元素为null则抛出NPE异常, 否则由于是无界队列,所以一直返回true。插入元素要实现 Delayed 接口。

§ poll ()

获取并移除队头过期元素,如果没有过期元素则返回 null。

§ take()

获取并移除队列里面延迟时间过期的元素,如果队列里面没有过期元素则等待。

size()

计算队列元素个数,包含过期的和没有过期的。

示例代码:

public class DelayQueueTest {
 static class Element implements Delayed {
 private final long delayTime; // 延迟时间
 private final long expire;; // 到期时间
 private String eleName; // 任务名称
 public Element(String eleName, long delay) {
 this.eleName = eleName;
 delayTime = delay;
 expire = System.currentTimeMillis() + delay;
 }
 public String getEleName() {
 return eleName;
 }
 public long getDelayTime() {
 return delayTime;
 }
 // 优先级队列里面的优先级规则
 @ Override 
 public int compareTo(Delayed o) {
 return (int) (this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS));
 }
 // 剩余时间=到期时间-当前时间
 @Override
 public long getDelay(TimeUnit unit) {
 return unit. convert (this.expire - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
 }
 }
 // 元素消费者
 static class Consumer implements Runnable {
 private DelayQueue< Element > queue;
 public Consumer(DelayQueue<Element> queue) {
 this.queue = queue;
 }
 @Override
 public void run() {
 while (true) {
 try {
 Element ele = queue.take();
 System.out.println("消费:" + ele.getEleName() + " 延时:" + ele.getDelayTime()+"ms");
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 }
 }
 }
 public static void main(String[] args) {
 // 创建延时队列
 DelayQueue<Element> delayQueue = new DelayQueue<Element>();
 // 添加延时元素1,延时3秒
 Element ele1 = new Element("元素1", 3000);
 delayQueue.offer(ele1);
 // 添加延时元素2,延时2秒
 Element ele2 = new Element("元素2", 2000);
 delayQueue.offer(ele2);
 // 添加延时元素3,延时1秒
 Element ele3 = new Element("元素3", 1000);
 delayQueue.offer(ele3);
 // 启动消费 线程  消费添加到延时队列中的消息,前提是任务到了延期时间
 Thread thd = new Thread(new Consumer(delayQueue));
 thd.start();
 }
}
 

运行结果如下图:

如上代码首先创建延迟任务 Element类, 其中 delayTime 表示当前元素需要延迟多少ms 时间过期, expire 则是当前时间的ms值加上delayTime的值。另外,实现了 Delayed 接口,实现了 long getDelay(TimeUnit unit)方法用来获取当前元素还剩下多少时间过期,实现了 int compareTo(Delayed o)方法用来决定优先级队列元素的 比较规则。

在main 函数内首先创建了一个延迟队列,然后放入不通延迟时间的三个元素,最后消费者线程从延时队列里取出元素。从运行结果可以看出,元素出队的顺序和delayTime时间有关,而与入队的顺序无关。

DelayQueue常见的使用场景有:

1. 缓存 的应用:具有过期时间的缓存

2. 订单支付业务:下单之后如果三十分钟之内没有付款就自动取消订单。

3. 订单通知业务:下单成功后60秒之后给用户发送短信通知。

文章来源:智云一二三科技

文章标题:java并发之DelayQueue类的介绍和使用

文章地址:https://www.zhihuclub.com/193067.shtml

关于作者: 智云科技

热门文章

网站地图