专栏首页凯哥JavaJava中常用的七个阻塞队列第二篇DelayQueue源码介绍
原创

Java中常用的七个阻塞队列第二篇DelayQueue源码介绍

Java中常用的七个阻塞队列第二篇DelayQueue源码介绍

通过前面两篇文章,我们对队列有了了解及已经认识了常用阻塞队列中的三个了。本篇我们继续介绍剩下的几个队列。

本文主要内容:通过源码学习Delayqueue及理解Dqueue并用代码简单演示使用场景。

本文出自凯哥Java(kaigejava)的《凯哥Java并发系列》之《Java并发编程之队列》系列的第三篇:《Java中常用的七个阻塞队列第二篇DelayQueue源码介绍》

Java中常用的几个队列中,阻塞队列还有四个没介绍。如下图:

DelayQueue

先上总结脑图:

编辑

来看看构造器:

支持无参和支持直接存放一个集合的。

再来看看为什么说DQueue队列使用的是PriorityQueue实现的呢?

来看看源码:

在添加元素的offer方法源码中,我们可以看到最终调用的是q.offer(e)这个方法的。那么q又是什么呢?我们接着跟下去:private final PriorityQueue<E> q = new PriorityQueue<E>();。发现q是PriorityQueue这个队列。如下图:

为什么说可以延时呢?

我们来看看DQueyue类的定义:

public class DelayQueue<E extends Delayed> extends AbstractQueue<E>

implements BlockingQueue<E> {}

从源码中,我们可以看到DQueue队列中存放的元素必须要实现Delayed接口。

我们在来看看Delayed接口的方法:

只有,long getDelay(TimeUnit unit);方法。设置等待时间。

在从队列中获取数据的时候会对超时时间进行判断的。当超时时间小于等于0的时候,才会调用priorityQueue队列的poll()方法。具体源码如下:

从源码中,我们可以看到,DQueue延时处理的:

无界怎么理解?

说DQueue无界,我们应该从源码中查找。DQueue队列是基于PriorityQueue队列来实现的。那么我们就来看看PriorityQueue队列添加元素的源码。

从上图中,我们可以看到,在添加元素的时候offer方法会进行判断,当i的值大于等于队列的长的时候,会调用grow()方法来进行扩容。在grow方法中,我们可以看到会使用Arrsys.copyof()方法复制一份给队列。这样队列就完成了库容。没有大小的限制。所以说是无界的。

阻塞理解

当队列为空的时候,“获取/取”元素操作将会block,被阻塞着。我们来看看源码是怎么实现的。

从源码中我们可以看到,当从队列中获取元素的时候,先判断,如果第一个元素为空的时候,就等待。当等待的时间小于等于延时时间的话,就从队列中poll了;如果leader不为空的话,说明当前队列不是队首元素,依然await。

支持优先级

因为在PQueue队列的添加方法中,使用了comparator.compare方法。源码如下图:

所以通过源码分析我们可以到得到DelayQueue如下脑图:

使用场景:

DQueue非常有用的。我们利用DQueue的延时特性,可以讲DQueue应用于以下场景:

1:缓存的设计。可以利用Dqueue保存缓存元素的有效期。使用一个线程循环的从队列中获取数据。一旦获取到数据,就说明缓存有效期到了。

2:定时任务调度。可以使用Dqueue保存需要执行的任务和任务执行的时间,一旦从DQueue中获取到了任务,就开始执行任务了。比如TimerQueue就是使用了DelayQueue来实现的。

下面凯哥(凯哥Java:kaigejava)通过代码简单演示模拟缓存过期时间的案例。

代码演示:

需求:模拟缓存设置有效期。

说明:当从队列中获取到元素,说明元素的有效期到了。

模拟缓存的对象:

构造器:

需要注意:time=传递的time+当前时间。

实现了Delayed接口,需要重写getDelay和compartTo方法。

重写方法如下:

返回的是time与当前时间之间的差值。

compareTo方法如下:

调用方法:

来看看运行结果:

从运行结果中,我们可以看到,从打印出开始获取到k1的输出之间相差1s;K1与k2之间相差2s;K3和K2之间也相差2s.符合我们上面预设的时间差。

《Javab并发JUC系列教程》:

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Java队列学习第一篇之列介绍

    队列大家都知道,但是在Java中队列分哪几种呢?清楚吗?都有哪些地方用到了队列呢?最常用的场景的就是消息中间件,比如各种MQ都是使用的队列来的。如果没有用过消息...

    凯哥Java
  • Java中常用七个阻塞队列的总结

    通过前面文章的学习,我们对Java中常用队列做了介绍。本文,咱们来对队列做个总结吧。

    凯哥Java
  • Java中常用的七个阻塞队列介绍第一篇

    在上一篇我们对Java中的队列分类做了简单的介绍。本文咱们主要来聊聊阻塞队列中的七个常用子类。这七个阻塞队列的学习步骤:先看源码,分析完源码之后,我们再来对每个...

    凯哥Java
  • 【FreeRTos】队列管理1

    写队列任务在每次循环中都调用taskYIELD()。taskYIELD()通知调度器立即进行任务切换,而不必等到当前任务的时间片耗尽。某个任务调用taskY...

    心跳包
  • 三分钟基础:什么是队列?

    像线程池、异步队列、消息队列等有限的资源容器中,往往存储大量的任务事件,这些大量的任务事件需要进行有条理的进行任务分发以及各种情况处理,为了能够使得资源容器的正...

    帅地
  • 算法与数据结构(二) 栈与队列的线性和链式表示(Swift版)

    数据结构中的栈与队列还是经常使用的,栈与队列其实就是线性表的一种应用。因为线性队列分为顺序存储和链式存储,所以栈可以分为链栈和顺序栈,队列也可分为顺序队列和链队...

    lizelu
  • 【数据结构(C语言版)系列三】 队列

    队列是一种先进先出的线性表,它只允许在表的一端进行插入,而在另一端删除元素。这和我们日常生活中的排队是一致的,最早进入队列的元素最早离开。在队列中,允许插入的一...

    闪电gogogo
  • Hadoop FairScheduler

    本文档描述FairScheduler,一个允许YARN应用程序公平共享集群资源的调度插件。

    用户1217611
  • 栈与队列:总结篇!

    相信不仅仅是C++中有这些问题,那么大家使用其他编程语言,也可以考虑一下这四个问题,栈和队列是如何实现的。

    代码随想录
  • AI_第一部分 数据结构与算法(8.队列)

    第四阶段我们进行深度学习(AI),本部分(第一部分)主要是对底层的数据结构与算法部分进行详尽的讲解,通过本部分的学习主要达到以下两方面的效果:

    还是牛6504957

扫码关注云+社区

领取腾讯云代金券