DelayQueue 是BlockingQueue接口的实现类,它根据"延时时间"来确定队列内的元素的处理优先级(即根据队列元素的“延时时间”进行排序)。另一层含义是只有那些超过“延时时间”的元素才能从队列里面被拿出来进行处理。

  • DelayQueue 队列将阻止其元素对象从队列中被取出,直到达到为元素对象设置的延迟时间。DelayQueue 在队列的头部存储最近过期的元素,如果队列内没有元素过期,使用poll()方法获取队列内的元素将会返回null。
  • DelayQueue 类及其迭代器实现了Collection和Iterator接口的所有可选方法,但迭代器方法iterator()不能保证以特定的顺序遍历DelayQueue的元素。

  • DelayQueue 不接收null元素,DelayQueue 只接受那些实现了java.util.concurrent.Delayed接口的对象,并将其放入队列内。DelayQueue 通过调用元素对象的getDelay(TimeUnit) 方法获取该元素剩余的“延迟时间”。getDelay()的 TimeUnit时间单位是一个枚举类型 : DAYS(天), HOURS(小时), MINUTES(分钟), SECONDS(秒), MILLISECONDS(毫秒), MICROSECONDS(微妙), NANOSECONDS(纳秒)
public interface Delayed extends Comparable{
   long getDelay(TimeUnit unit);
}

下面我们就写一个java Class实现Delayed 接口,只有实现了Delayed 接口的类对象才能放入DelayQueue。因为Delayed接口继承自Comparable接口,所以我们必须实现getDelay方法和compareTo方法。

class DelayObject implements Delayed {
private String name;
private long time; //延时时间 public DelayObject(String name, long delayTime) {
this.name = name;
this.time = System.currentTimeMillis() + delayTime;
} @Override
public long getDelay(TimeUnit unit) {
long diff = time - System.currentTimeMillis();
return unit.convert(diff, TimeUnit.MILLISECONDS);
} @Override
public int compareTo(Delayed obj) {
if (this.time < ((DelayObject)obj).time) {
return -1;
}
if (this.time > ((DelayObject)obj).time) {
return 1;
}
return 0;
} @Override
public String toString() {
Date date = new Date(time);
SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); return "\nDelayObject:{"
+ "name=" + name
+ ", time=" + sd.format(date)
+ "}";
}
}

测试延时队列DelayQueue的使用效果

public class DelayQueueTest {

  @Test
void testDelayObject() throws InterruptedException { //实例化一个DelayQueue
BlockingQueue<DelayObject> DQ = new DelayQueue<>(); //向DelayQueue添加四个元素对象,注意延时时间不同
DQ.add(new DelayObject("A", 1000 * 10)); //延时10秒
DQ.add(new DelayObject("B", 4000 * 10)); //延时40秒
DQ.add(new DelayObject("C", 3000 * 10)); //延时30秒
DQ.add(new DelayObject("D", 2000 * 10)); //延时20秒 SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //将对象从DelayQueue取出,注意取出的顺序与延时时间有关
System.out.println( DQ.take()); //取出A
System.out.println( DQ.take()); //取出D
System.out.println( DQ.take()); //取出C
System.out.println( DQ.take()); //取出B }
}

从下面的打印结果及上文的代码可以看出

  • 队列中元素放入的顺序是A、B、C、D,取出的顺序是A、D、C、B,这是因为队列中的元素按照延时时间进行了排序。
  • 另外我们可以看到,每隔10秒才可以从队列中取出一个元素,这是因为只有超过“延时时间”的元素才能从队列里面被拿出来。而我们设置的延时时间是10s、20s、30s、40s。
DelayObject:{name=A, time=2021-03-23 14:14:20}

DelayObject:{name=D, time=2021-03-23 14:14:30}

DelayObject:{name=C, time=2021-03-23 14:14:40}

DelayObject:{name=B, time=2021-03-23 14:14:50}

欢迎关注我的博客,里面有很多精品合集

  • 本文转载注明出处(必须带连接,不能只转文字):字母哥博客。

觉得对您有帮助的话,帮我点赞、分享!您的支持是我不竭的创作动力! 。另外,笔者最近一段时间输出了如下的精品内容,期待您的关注。

java并发编程工具类JUC第三篇:DelayQueue延时队列的更多相关文章

  1. java并发编程工具类JUC第四篇:LinkedBlockingQueue链表队列

    在之前的文章中已经为大家介绍了java并发编程的工具:BlockingQueue接口.ArrayBlockingQueue.DelayQueue. LinkedBlockingQueue 队列是Blo ...

  2. java并发编程工具类JUC第七篇:BlockingDeque双端阻塞队列

    在之前的文章中已经为大家介绍了java并发编程的工具:BlockingQueue接口.ArrayBlockingQueue.DelayQueue.LinkedBlockingQueue.Priorit ...

  3. java并发编程工具类JUC第八篇:ConcurrentHashMap

    在之前的文章中已经为大家介绍了java并发编程的工具:BlockingQueue接口.ArrayBlockingQueue.DelayQueue.LinkedBlockingQueue.Priorit ...

  4. java并发编程工具类JUC第一篇:BlockingQueue阻塞队列

    Java BlockingQueue接口java.util.concurrent.BlockingQueue表示一个可以存取元素,并且线程安全的队列.换句话说,当多线程同时从 JavaBlocking ...

  5. java并发编程工具类JUC第二篇:ArrayBlockingQueue

    类ArrayBlockingQueue是BlockingQueue接口的实现类,它是有界的阻塞队列,内部使用数组存储队列元素.这里的"有界"是指存储容量存在上限,不能无限存储元素. ...

  6. Java并发编程工具类 CountDownLatch CyclicBarrier Semaphore使用Demo

    Java并发编程工具类 CountDownLatch CyclicBarrier Semaphore使用Demo CountDownLatch countDownLatch这个类使一个线程等待其他线程 ...

  7. java并发编程工具类辅助类:CountDownLatch、CyclicBarrier和 Semaphore

    在java 1.5中,提供了一些非常有用的辅助类来帮助我们进行并发编程,比如CountDownLatch,CyclicBarrier和Semaphore,今天我们就来学习一下这三个辅助类的用法. 以下 ...

  8. 【java并发编程艺术学习】(三)第二章 java并发机制的底层实现原理 学习记录(一) volatile

    章节介绍 这一章节主要学习java并发机制的底层实现原理.主要学习volatile.synchronized和原子操作的实现原理.Java中的大部分容器和框架都依赖于此. Java代码 ==经过编译= ...

  9. Java并发编程入门,看这一篇就够了

    Java并发编程一直是Java程序员必须懂但又是很难懂的技术内容.这里不仅仅是指使用简单的多线程编程,或者使用juc的某个类.当然这些都是并发编程的基本知识,除了使用这些工具以外,Java并发编程中涉 ...

随机推荐

  1. GO-02-helloworld

    package main /** package main表示一个可独立执行的程序,每个Go应用程序都需要包含一个名为main的包, 并且该包包含一个叫main()的函数(该函数是Go可执行程序的执行 ...

  2. 906. Super Palindromes

    Let's say a positive integer is a superpalindrome if it is a palindrome, and it is also the square o ...

  3. git基于master创建本地新分支

    应用场景:开发过程中经常用到从master分支copy一个本地分支作为开发分支 步骤: 1.切换到被copy的分支(master),并且从远端拉取最新版本 $git checkout master $ ...

  4. animation几个比较好玩的属性(alternate,及animation-fill-mode)

    <!DOCTYPE html> <html> <head> <style> div { width:100px; height:100px; backg ...

  5. hdu4535

    题意: 吉哥系列故事--礼尚往来 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) To ...

  6. CVE-2011-0104:Microsoft Office Excel 栈溢出漏洞修复分析

    0x01 前言 上一篇讲到了 CVE-2011-0104 漏洞的成因和分析的方法,并没有对修复后的程序做分析.之后在一次偶然的情况下,想看一看是怎么修复的,结果却发现了一些问题 环境:修复后的 EXC ...

  7. XCTF-shrine

    shrine 直接看题 进来给了个python代码 import flask import os app = flask.Flask(__name__) app.config['FLAG'] = os ...

  8. 【python】Leetcode每日一题-打家劫舍2

    [python]Leetcode每日一题-打家劫舍2 [题目描述] 你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金.这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋 ...

  9. Git(2)多人协同操作冲突

    一:多人协同操作冲突 拉取远程dev并在本地创建dev开发库,执行命令git checkout -b  dev  origin/dev  这里以同台机器不同窗口来模拟俩个用户操作同一分支同一文件(实际 ...

  10. Redis数据结构—链表与字典

    目录 Redis数据结构-链表与字典 链表 Redis链表节点的结构 Redis链表的表示 Redis链表用在哪 字典 Redis字典结构总览 Redis字典结构分解 哈希算法 解决键冲突 rehas ...