一篇文章搞懂 DelayQueue

2023-12-08 08:58

本文主要是介绍一篇文章搞懂 DelayQueue,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

本文隶属于专栏《100个问题搞定Java并发》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢!

本专栏目录结构和参考文献请见100个问题搞定Java并发

正文

WHAT

DelayQueue 是一个无界阻塞队列( BlockingQueue ),用于放置实现了 Delayed 接口的对象,其中的对象只能在其到期时才能从队列中取走。

关于 BlockingQueue 请参考我的博客——BlockingQueue 源码解析(JDK8)

这种队列是有序的,因此队首对象的延迟到期的时间最长。

如果没有任何延迟到期,那么就不会有队首元素,并且 poll() 将返回 null (正因为这样,你不能将 null 放置到这种队列中)。

实践

下面是一个示例,其中的 Delayed 对象自身就是任务,而 DelayedTaskConsumer 将最“紧急”的任务(到期时间最长的任务)从队列中取出,然后运行它。

注意的是这样的 DelayQueue 就成为了优先级队列的一种变体。

package com.shockang.study.java.concurrent.blocking_queue;import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.NANOSECONDS;class DelayedTask implements Runnable, Delayed {private static int counter = 0;private final int id = counter++;private final int delta;private final long trigger;protected static List<DelayedTask> sequence = new ArrayList<>();DelayedTask(int delayInMilliseconds) {delta = delayInMilliseconds;trigger = System.nanoTime() + NANOSECONDS.convert(delta, MILLISECONDS);sequence.add(this);}@Overridepublic long getDelay(TimeUnit unit) {return unit.convert(trigger - System.nanoTime(), NANOSECONDS);}@Overridepublic int compareTo(Delayed arg) {DelayedTask that = (DelayedTask) arg;if (trigger < that.trigger) return -1;if (trigger > that.trigger) return 1;return 0;}@Overridepublic void run() {System.out.print(this + " ");}@Overridepublic String toString() {return String.format("[%d] Task %d", delta, id);}public String summary() {return String.format("(%d:%d)", id, delta);}public static class EndTask extends DelayedTask {EndTask(int delay) {super(delay);}@Overridepublic void run() {sequence.forEach(dt -> System.out.println(dt.summary()));}}
}public class DelayQueueDemo {public static voidmain(String[] args) throws Exception {DelayQueue<DelayedTask> tasks = Stream.concat(new Random(47).ints(20, 0, 4000).mapToObj(DelayedTask::new),Stream.of(new DelayedTask.EndTask(4000))).collect(Collectors.toCollection(DelayQueue::new));while (tasks.size() > 0)tasks.take().run();}
}
[128] Task 12 [429] Task 6 [551] Task 13 [555] Task 2 [693] Task 3 [809] Task 15 [961] Task 5 [1258] Task 1 [1258] Task 20 [1520] Task 19 [1861] Task 4 [1998] Task 17 [2200] Task 8 [2207] Task 10 [2288] Task 11 [2522] Task 9 [2589] Task 14 [2861] Task 18 [2868] Task 7 [3278] Task 16 (0:4000)
(1:1258)
(2:555)
(3:693)
(4:1861)
(5:961)
(6:429)
(7:2868)
(8:2200)
(9:2522)
(10:2207)
(11:2288)
(12:128)
(13:551)
(14:2589)
(15:809)
(16:3278)
(17:1998)
(18:2861)
(19:1520)
(20:1258)

DelayedTask 包含一个称为 sequence 的 List< DelayedTask>,它保存了任务被创建的顺序,因此我们可以看到排序是按照实际发生的顺序执行的

Delay 接口有一个方法, getDelay(),该方法用来告知延迟到期有多长时间,或者延迟在多长时间之前已经到期了。

这个方法强制我们去使用 Timeunit 类,因为这就是参数类型。

这会产生一个非常方便的类,因为你可以很容易地转换单位而无需作任何声明。

例如, delta 的值是以毫秒为单位存储的,但是 System.nanotime ()产生的时间则是以纳秒为单位的。

你可以转换 delta 的值,方法是声明它的单位以及你希望以什么单位来表示,就像下面这样。

NANOSECONDS.convert(delta, MILLISECONDS);

在 getDelay()中,所希望的单位是作为 unit 参数传递进来的,你使用它将当前时间与触发时间之间的差转换为调用者要求的单位,而无需知道这些单位是什么(这是策略设计模式的一个简单示例,在这种模式中,算法的一部分是作为参数传递进来的)。

为了排序, Delayed 接口还继承了 Comparable 接口,因此必须实现 compareTo(),使其可以产生合理的比较。

从输出中可以看到,任务创建的顺序对执行顺序没有任何影响-相反,任务是按照所期望的延迟顺序所执行的。

这篇关于一篇文章搞懂 DelayQueue的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/469267

相关文章

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

java计算机毕设课设—停车管理信息系统(附源码、文章、相关截图、部署视频)

这是什么系统? 资源获取方式在最下方 java计算机毕设课设—停车管理信息系统(附源码、文章、相关截图、部署视频) 停车管理信息系统是为了提升停车场的运营效率和管理水平而设计的综合性平台。系统涵盖用户信息管理、车位管理、收费管理、违规车辆处理等多个功能模块,旨在实现对停车场资源的高效配置和实时监控。此外,系统还提供了资讯管理和统计查询功能,帮助管理者及时发布信息并进行数据分析,为停车场的科学

CSP-J基础之数学基础 初等数论 一篇搞懂(一)

文章目录 前言声明初等数论是什么初等数论历史1. **古代时期**2. **中世纪时期**3. **文艺复兴与近代**4. **现代时期** 整数的整除性约数什么样的整数除什么样的整数才能得到整数?条件:举例说明:一般化: 判断两个数能否被整除 因数与倍数质数与复合数使用开根号法判定质数哥德巴赫猜想最大公因数与辗转相除法计算最大公因数的常用方法:举几个例子:例子 1: 计算 12 和 18

文章解读与仿真程序复现思路——电力自动化设备EI\CSCD\北大核心《考虑燃料电池和电解槽虚拟惯量支撑的电力系统优化调度方法》

本专栏栏目提供文章与程序复现思路,具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源程序擅长文章解读,论文与完整源程序,等方面的知识,电网论文源程序关注python

CSP-J基础之数学基础 初等数论 一篇搞懂(二)

文章目录 前言算术基本定理简介什么是质数?举个简单例子:重要的结论:算术基本定理公式解释:举例: 算术基本定理的求法如何找出质因数:举个简单的例子: 重要的步骤:C++实现 同余举个例子:同余的性质简介1. 同余的自反性2. 同余的对称性3. 同余的传递性4. 同余的加法性质5. 同余的乘法性质 推论 总结 前言 在计算机科学和数学中,初等数论是一个重要的基础领域,涉及到整数

【Linux】萌新看过来!一篇文章带你走进Linux世界

🚀个人主页:奋斗的小羊 🚀所属专栏:Linux 很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~ 目录 前言💥1、初识Linux💥1.1 什么是操作系统?💥1.2 各种操作系统对比💥1.3 现代Linux应用💥1.4 Linux常用版本 💥2、Linux 和 Windows 目录结构对比💥2.1 文件系统组织方式💥2.2

多线程的系列文章

Java多线程学习(一)Java多线程入门 Java多线程学习(二)synchronized关键字(1)   Java多线程学习(二)synchronized关键字(2) Java多线程学习(三)volatile关键字 Java多线程学习(四)等待/通知(wait/notify)机制 Java多线程学习(五)线程间通信知识点补充 Java多线程学习(六)Lock锁的使用 Java多

缓存的常见问题 以及解决博客文章

1.jedispool 连 redis 高并发卡死  (子非鱼yy) https://blog.csdn.net/ztx114/article/details/78291734 2. Redis安装及主从配置 https://blog.csdn.net/ztx114/article/details/78320193 3.Spring中使用RedisTemplate操作Redis(sprin

java计算机毕设课设—企业员工信息管理系统(附源码、文章、相关截图、部署视频)

这是什么系统? 获取资料方式在最下方 java计算机毕设课设—企业员工信息管理系统(附源码、文章、相关截图、部署视频) 企业员工信息管理系统旨在为公司提供高效的员工信息管理解决方案。该系统的核心功能涵盖密码修改、员工管理、部门管理、出勤管理、工资管理、请假审核等方面,帮助企业优化人力资源管理流程。系统结构如下: (1)前端(员工端): 1.密码修改:员工可以修改自己的密码,提升账户的安全

AI产品经理:ai产品经理从零基础到精通,非常详细收藏我这一篇就够了

在互联网的浪潮中,AI人工智能领域无疑是最引人注目的风口。AI产品经理,作为这一领域的新兴岗位,以其高薪、低压力、无年龄限制等优势,吸引了众多互联网从业者的目光。随着GPT等AIGC工具的兴起,AI产品经理的市场需求日益增长。 AI产品经理需不需要懂算法?🤔‍‍‍ AI产品经理不必像算法工程师那样精通算法,但必须能够与算法工程师有效沟通,了解如何管理AI项目,协调项目资源。 成功转行AI产