DelayQueue简介DelayQueue是JUC包(java.util.concurrent)为我们提供的延迟队列,它是一个基于PriorityQueue实现的一个无界队列,是一个线程安全的延迟队列。关于PriorityQueue可以参考笔者编写的这篇文章:PriorityQueue源码分析当我们希望某个任务在某个时间才能取出并操作时,我们就可以让这个继承Delayed接口,实现其计算任务到期时间的方法 getDelay 。然后将任务存放到 DelayQueue 中,默认情况下, DelayQueue 会按照到期时间升序编排任务。随后当 DelayQueue 发现任务到期时,我们才能从 DelayQueue 中取出这个任务并执行。这使得 DelayQueue非常适合运用于以下两种场景:定时任务 : DelayQueue 非常适合用于处理那些到期才能执行的任务,例如用户触发下单请求,我们规定15min后未支付则取消订单,那么我们就可以提交一个15min后到查询用户下单情况的任务给DelayQueue,如果15min后取出该任务发现用户还未下单,则取消这个订单。缓存过期 : 假如我们使用Java维护一个内存,我们希望缓存具备时效性,同样我们可以封装一个缓存过期删除的任务提交到DelayQueue,DelayQueue会在到期后取出这个任务并将缓存数据删除。DelayQueue发展史DelayQueue 最早是在 Java 5 中引入的,作为 java.util.concurrent 包中的一部分,用于支持基于时间的任务调度和缓存过期删除等场景,该版本仅仅支持延迟功能的实现,还未解决线程安全问题。在 Java 6 中,DelayQueue 的实现进行了优化,通过使用 ReentrantLock 和 Condition 解决线程安全及线程间交互的效率,提高了其性能和可靠性。在 Java 7 中,DelayQueue 的实现进行了进一步的优化,通过使用 CAS 操作实现元素的添加和移除操作,提高了其并发操作性能。在 Java 8 中,DelayQueue 的实现没有进行重大变化,但是在 java.time 包中引入了新的时间类,如 Duration 和 Instant,使得使用 DelayQueue 进行基于时间的调度更加方便和灵活。在 Java 9 中,DelayQueue 的实现进行了一些微小的改进,主要是对代码进行了一些优化和精简。总的来说,DelayQueue 的发展史主要是通过优化其实现方式和提高其性能和可靠性,使其更加适用于基于时间的调度和缓存过期删除等场景。DelayQueue常见使用场景示例定时任务我们希望任务可以按照我们预期的时间执行,例如提交3个任务,分别要求1s、2s、3s后执行,即使是乱序添加,1s后要求1s执行的任务会准时执行。对此我们可以使用DelayQueue来实现,所以我们首先需要继承Delayed实现 DelayedTask,实现getDelay方法以及优先级比较compareTo。/** * 延迟任务 */ public class DelayedTask implements Delayed{/** * 任务到期时间 */ private long executeTime;/** * 任务 */ private Runnable task;public DelayedTask(long delay, Runnable task){this.executeTime=System.currentTimeMillis()+ delay;this.task=task;}/** * 查看当前任务还有多久到期 * @param unit * @return */ @Override public long getDelay(TimeUnit unit){returnunit.convert(executeTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);}/** * 延迟队列需要到期时间升序入队,所以我们需要实现compareTo进行到期时间比较 * @param o * @return */ @Override public int compareTo(Delayed o){returnLong.compare(this.executeTime,((DelayedTask)o).executeTime);}public voidexecute(){task.run();}}完成任务的封装之后,使用就很简单了,设置好多久到期然后将任务提交到延迟队列中即可。public static void main(String[]args)throws InterruptedException{// 创建延迟队列,并添加任务 DelayQueueDelayedTaskdelayQueue=new DelayQueue();//分别添加1s、2s、3s到期的任务 delayQueue.add(new DelayedTask(2000,()-System.out.println("Task 2")));delayQueue.add(new DelayedTask(1000,()-System.out.println("Task 1")));delayQueue.add(new DelayedTask(3000,()-System.out.println("Task 3")));// 取出任务并执行while(!delayQueue.isEmpty()){//阻塞获取最先到期的任务 DelayedTask task=delayQueue.take();if(task!=null){task.execute();