`

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.符合我们上面预设的时间差。

《Java并发系列教程》:

 

0
1
分享到:
评论

相关推荐

    java利用delayedQueue实现本地的延迟队列

    DelayQueue 提供了一个无界的阻塞队列,用于存放实现了 Delayed 接口的对象。 DelayQueue 能够保证队列中的对象是有序的,即队头对象的延迟到期时间最长。 DelayQueue 的使用场景非常广泛,如: 1. 订单业务中,...

    DelayQueue延迟队列和Redis缓存实现订单自动取消功能

    在Java编程中,DelayQueue是一种特殊的并发队列,它遵循先进先出(FIFO)原则,但具有一个独特的特性:元素只有在其指定的延迟时间过去之后才能被获取和处理。这个特性使得DelayQueue成为实现定时任务和延迟操作的...

    JDK自带的延迟队列-DelayQueue

    在Java的并发编程中,`DelayQueue`是一个非常特殊的队列,它属于并发包`java.util.concurrent`的一部分。`DelayQueue`是一个基于优先级队列(PriorityQueue)实现的无界阻塞队列,它的主要特性是元素只有在达到指定...

    java学习(基于Java阻塞队列的搜索实例).pdf

    在Java中,`java.util.concurrent`包提供了多种阻塞队列实现,包括`LinkedBlockingQueue`、`ArrayBlockingQueue`、`PriorityBlockingQueue`和`DelayQueue`。 `ArrayBlockingQueue`是一个有界的并发队列,它在创建时...

    14-阻塞队列BlockingQueue实战及其原理分析二.pdf

    阻塞队列(BlockingQueue)是一种特殊的队列,它支持两个附加操作:阻塞的插入方法put和阻塞的移除方法take。BlockingQueue继承了Queue接口,是Java 5中加入的。 BlockingQueue常用方法示例: 1. add(E e):添加一...

    Java并发编程相关源码集 包括多任务线程,线程池等.rar

    多个线程竞争问题、多个线程多个锁问题、创建一个缓存的线程池、多线程使用Vector或者HashTable的示例(简单线程同步问题)、PriorityBlockingQueue示例、高性能无阻塞无界队列: ConcurrentLinkedQueue、DelayQueue...

    DelayQueue、Redis结合使延迟、定时任务使用源代码

    `DelayQueue`是Java并发库`java.util.concurrent`中的一个数据结构,它是一个基于优先级队列的无界阻塞队列,可以用于存储具有延迟时间的元素。而Redis则是一个高性能的键值数据库,通过其丰富的数据结构和操作,...

    Java并发编程(21)并发新特性-阻塞队列和阻塞栈(含代

    在实际开发中,我们可以使用阻塞队列来构建生产者消费者模型。生产者将任务放入队列,消费者从队列中取出任务执行。以下是一个简单的`ArrayBlockingQueue`使用示例: ```java import java.util.concurrent....

    剖析Java中阻塞队列的实现原理及应用场景

    Java中的阻塞队列是一种特殊的线程安全的数据结构,它在多线程环境下用于高效地处理生产者-消费者问题。阻塞队列的核心特性在于当...在实际开发中,合理使用阻塞队列可以极大地提升多线程环境下的程序性能和可维护性。

    java concurrent 精简源码

    本资源“java concurrent 精简源码”着重关注Java并发库(java.util.concurrent)的核心概念,包括阻塞队列和线程管理。下面将详细阐述这些知识点。 1. **Java并发库(java.util.concurrent)** Java并发库是Java ...

    阻塞队列(Blocking Queue)是一个支持两个附加操作的队列.txt

    阻塞队列是Java中并发编程的一个重要组件,它属于Java.util.concurrent包中的一部分。...使用阻塞队列能够极大地简化生产者和消费者模型的实现,并且能够在多线程环境中更加有效地管理资源和任务。

    Java中的阻塞队列详细介绍

    使用阻塞队列时,生产者通常使用`put()`或`offer()`方法添加元素,而消费者则使用`take()`或`poll()`方法取出元素。阻塞队列的实现依赖于底层的锁机制,如`ReentrantLock`,以及条件变量,如`Condition`,来确保线程...

    java队列Java系列2021.pdf

    线程安全的队列实现方式通常有两种:一种是使用阻塞队列,另一种是使用线程同步锁。阻塞队列是一种特殊的队列,它支持阻塞的插入和移除操作。在队列满时,尝试插入元素的线程会被阻塞,直到队列有空间;在队列空时,...

    高效的实现队列

    它可能包含了上述某一种或多种队列的实现,例如用C++、Java或其他编程语言实现的简单队列、阻塞队列、并发队列等。具体的实现细节需要查看源代码才能得知。 在实际应用中,队列常被用于任务调度、消息传递、网络...

    Java多线程并发开发之DelayQueue使用示例

    "Java多线程并发开发之DelayQueue使用示例" DelayQueue是Java多线程并发开发中的一种常用的数据结构,它是一个无界的BlockingQueue,用于放置实现了Delayed接口的对象。DelayQueue的主要作用是按照对象的延迟时间...

    10、阻塞队列BlockingQueue实战及其原理分析.pdf

    5. **并发任务处理**:多个工作线程可以从队列中取出任务进行处理,使用阻塞队列可以避免多个线程同时处理同一个任务的问题。 #### 二、阻塞队列的接口方法 阻塞队列的接口方法大致可以分为三类: 1. **抛出异常*...

    基于Redis实现的延迟消息队列

    整个延迟队列由4个部分组成: 1. JobPool用来存放所有Job的元信息。 2. DelayBucket是一组以时间为维度的有序队列,用来存放所有需要延迟的Job(这里只存放Job Id)。 3. Timer负责实时扫描各个Bucket,并将delay...

    java并发工具包 java.util.concurrent中文版用户指南pdf

    4. 延迟队列 DelayQueue 5. 链阻塞队列 LinkedBlockingQueue 6. 具有优先级的阻塞队列 PriorityBlockingQueue 7. 同步队列 SynchronousQueue 8. 阻塞双端队列 BlockingDeque 9. 链阻塞双端队列 LinkedBlockingDeque ...

    Java中使用阻塞队列控制线程集实例

    在Java编程中,阻塞队列(BlockingQueue)是一种重要的并发工具,用于在多个线程之间传递和协调任务。在上述实例中,阻塞队列被用来控制线程集,以便在目录及其子目录中搜索包含特定关键字的文件。这个程序涉及到几...

Global site tag (gtag.js) - Google Analytics