java中DelayQueue的使用
java中DelayQueue的使用
简介
今天给大家介绍一下DelayQueue,DelayQueue是BlockingQueue的一种,所以它是线程安全的,DelayQueue的特点就是插入Queue中的数据可以按照自定义的delay时间进行排序。只有delay时间小于0的元素才能够被取出。
DelayQueue
先看一下DelayQueue的定义:
public class DelayQueue<E extends Delayed> extends AbstractQueue<E>
implements BlockingQueue<E>
从定义可以看到,DelayQueue中存入的对象都必须是Delayed的子类。
Delayed继承自Comparable,并且需要实现一个getDelay的方法。
为什么这样设计呢?
因为DelayQueue的底层存储是一个PriorityQueue,在之前的文章中我们讲过了,PriorityQueue是一个可排序的Queue,其中的元素必须实现Comparable方法。而getDelay方法则用来判断排序后的元素是否可以从Queue中取出。
DelayQueue的应用
DelayQueue一般用于生产者消费者模式,我们下面举一个具体的例子。
首先要使用DelayQueue,必须自定义一个Delayed对象:
@Data
public class DelayedUser implements Delayed {
private String name;
private long avaibleTime;
public DelayedUser(String name, long delayTime){
this.name=name;
//avaibleTime = 当前时间+ delayTime
this.avaibleTime=delayTime + System.currentTimeMillis();
}
@Override
public long getDelay(TimeUnit unit) {
//判断avaibleTime是否大于当前系统时间,并将结果转换成MILLISECONDS
long diffTime= avaibleTime- System.currentTimeMillis();
return unit.convert(diffTime,TimeUnit.MILLISECONDS);
}
@Override
public int compareTo(Delayed o) {
//compareTo用在DelayedUser的排序
return (int)(this.avaibleTime - ((DelayedUser) o).getAvaibleTime());
}
}
上面的对象中,我们需要实现getDelay和compareTo方法。
接下来我们创建一个生产者:
@Slf4j
@Data
@AllArgsConstructor
class DelayedQueueProducer implements Runnable {
private DelayQueue<DelayedUser> delayQueue;
private Integer messageCount;
private long delayedTime;
@Override
public void run() {
for (int i = 0; i < messageCount; i++) {
try {
DelayedUser delayedUser = new DelayedUser(
new Random().nextInt(1000)+"", delayedTime);
log.info("put delayedUser {}",delayedUser);
delayQueue.put(delayedUser);
Thread.sleep(500);
} catch (InterruptedException e) {
log.error(e.getMessage(),e);
}
}
}
}
在生产者中,我们每隔0.5秒创建一个新的DelayedUser对象,并入Queue。
再创建一个消费者:
@Slf4j
@Data
@AllArgsConstructor
public class DelayedQueueConsumer implements Runnable {
private DelayQueue<DelayedUser> delayQueue;
private int messageCount;
@Override
public void run() {
for (int i = 0; i < messageCount; i++) {
try {
DelayedUser element = delayQueue.take();
log.info("take {}",element );
} catch (InterruptedException e) {
log.error(e.getMessage(),e);
}
}
}
}
在消费者中,我们循环从queue中获取对象。
最后看一个调用的例子:
@Test
public void useDelayedQueue() throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(2);
DelayQueue<DelayedUser> queue = new DelayQueue<>();
int messageCount = 2;
long delayTime = 500;
DelayedQueueConsumer consumer = new DelayedQueueConsumer(
queue, messageCount);
DelayedQueueProducer producer = new DelayedQueueProducer(
queue, messageCount, delayTime);
// when
executor.submit(producer);
executor.submit(consumer);
// then
executor.awaitTermination(5, TimeUnit.SECONDS);
executor.shutdown();
}
上面的测试例子中,我们定义了两个线程的线程池,生产者产生两条消息,delayTime设置为0.5秒,也就是说0.5秒之后,插入的对象能够被获取到。
线程池在5秒之后会被关闭。
运行看下结果:
[pool-1-thread-1] INFO com.flydean.DelayedQueueProducer - put delayedUser DelayedUser(name=917, avaibleTime=1587623188389)
[pool-1-thread-2] INFO com.flydean.DelayedQueueConsumer - take DelayedUser(name=917, avaibleTime=1587623188389)
[pool-1-thread-1] INFO com.flydean.DelayedQueueProducer - put delayedUser DelayedUser(name=487, avaibleTime=1587623188899)
[pool-1-thread-2] INFO com.flydean.DelayedQueueConsumer - take DelayedUser(name=487, avaibleTime=1587623188899)
我们看到消息的put和take是交替进行的,符合我们的预期。
如果我们做下修改,将delayTime修改为50000,那么在线程池关闭之前插入的元素是不会过期的,也就是说消费者是无法获取到结果的。
总结
DelayQueue是一种有奇怪特性的BlockingQueue,可以在需要的时候使用。
本文的例子https://github.com/ddean2009/learn-java-collections
欢迎关注我的公众号:程序那些事,更多精彩等着您!
更多内容请访问 www.flydean.com
java中DelayQueue的使用的更多相关文章
- java中DelayQueue的一个使用陷阱分析
最近工作中有接触到DelayQueue,网上搜索资料的时候发现一篇文章谈到DelayQueue的坑.点击打开链接 文中已经总结了遇到坑的地方,还有解决方案.不过我第一眼看一下没弄明白为什么,所以翻了翻 ...
- 延时队列:Java中的DelayQueue
Java中的DelayQueue位于java.util.concurrent包下,本质是由PriorityQueue和BlockingQueue实现的阻塞优先级队列. 放入队列的元素需要实现java. ...
- Java中常用的七个阻塞队列第二篇DelayQueue源码介绍
Java中常用的七个阻塞队列第二篇DelayQueue源码介绍 通过前面两篇文章,我们对队列有了了解及已经认识了常用阻塞队列中的三个了.本篇我们继续介绍剩下的几个队列. 本文主要内容:通过源码学习De ...
- Java中的多线程你只要看这一篇就够了
学习Java的同学注意了!!! 学习过程中遇到什么问题或者想获取学习资源的话,欢迎加入Java学习交流群,群号码:279558494 我们一起学Java! 引 如果对什么是线程.什么是进程仍存有疑惑, ...
- 聊聊并发(七)——Java中的阻塞队列
3. 阻塞队列的实现原理 聊聊并发(七)--Java中的阻塞队列 作者 方腾飞 发布于 2013年12月18日 | ArchSummit全球架构师峰会(北京站)2016年12月02-03日举办,了解更 ...
- [转]Java中的多线程你只要看这一篇就够了
如果对什么是线程.什么是进程仍存有疑惑,请先Google之,因为这两个概念不在本文的范围之内. 用多线程只有一个目的,那就是更好的利用cpu的资源,因为所有的多线程代码都可以用单线程来实现.说这个话其 ...
- java中的各种Queue
java中的各种并发Queue可以归为以下的几种: ConcurrentLinkedQueue: 一个由链表结构组成的非阻塞队列 ArrayBlockingQueue :一个由数组结构组成的有界阻塞队 ...
- 一篇图看清Java中的各种Queue
说到数据结构,我们大概可以列出这么几个:数组,链表,栈,队列,集合,哈希表. 其中 队列 作为一个常用的数据结构,在Java中也有各种形式的实现. 顶级接口为java.util.queue. java ...
- Java 中的多线程你只要看这一篇就够了
引 如果对什么是线程.什么是进程仍存有疑惑,请先Google之,因为这两个概念不在本文的范围之内. 用多线程只有一个目的,那就是更好的利用cpu的资源,因为所有的多线程代码都可以用单线程来实现.说这个 ...
- Java 中的队列 Queue
一.队列的定义 我们都知道队列(Queue)是一种先进先出(FIFO)的数据结构,Java中定义了java.util.Queue接口用来表示队列.Java中的Queue与List.Set属于同一个级别 ...
随机推荐
- 基于javaweb的服装租赁网站
演示 技术+环境+工具 jdk8+maven.3.2.1+mysql5.7+idea+navicat+spring+springmvc+mybatis+bootstrap+jquery+ajax
- 【LeetCode贪心#07】分糖果(两个维度)
发糖果 力扣题目链接(opens new window) 老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分. 你需要按照以下要求,帮助老师给这些孩子分发糖 ...
- 【Azure Redis 缓存】如何使得Azure Redis可以仅从内网访问? Config 及 Timeout参数配置
问题描述 问题一:Redis服务,如何可以做到仅允许特定的子网内的服务器进行访问? 问题二:Redis服务,timeout和keepalive的设置是怎样的?是否可以配置成timeout 0? 问题三 ...
- 【Azure 环境】Update-MgEntitlementManagementAccessPackageAssignmentPolicy 命令执行时候遇见的 No HTTP Resource was found 问题分析
Microsoft Graph PowerShell SDK: acts as an API wrapper for the Microsoft Graph APIs, exposing the en ...
- Python魔法:20个让你编程事半功倍的奇淫技巧(建议收藏)
Python作为一门灵活.充满技巧的语言,有着很多奇技淫巧,今天小编就跟大家分享一下在平时工作中所积累的技巧,这里面既有语法上的技巧,也有库函数的应用,可以帮助大家在平时的工作中提升效率,规避某些错误 ...
- 如何避免MYSQL主从延迟带来的读写问题?
在MYSQL 部署架构选型上,许多公司都会用到主从读写分离的架构,如下是一个一主一从的架构,主库master负责写入,从库slave进行读取. 但是既然是读写分离,必然会面临这样一个问题,当在主库上进 ...
- 2.4G无线音频传输方案市场调研分析
基本概念 所谓的2.4G音频传输,不是使用标准的wifi和蓝牙协议传输,而是使用私有的2.4G通信协议来实现点对点,一对多和多对一的音频传输.2.4G私有协议音频传输,有这低延时,距离远,声音高清 ...
- 回声消除AEC(Acoustic Echo Cancellation)概括介绍及基本原理分析
回声消除的基本概念 回音消除(Acoustic Echo Cancelling)是透过音波干扰方式消除麦克风与喇叭因空气产生回受路径(feedback path)而产生的杂音.通俗一点来说,回声消 ...
- day08-2-Thymeleaf
服务器渲染技术-Thymeleaf 1.基本介绍 官方在线文档:Read online 文档下载:Thymeleaf 3.1 PDF, EPUB, MOBI Thymeleaf 是什么 Thymele ...
- 【Jmeter】性能测试--EMQ X 压测
一.业务背景 开发人员需要验证 EMQ X 性能参数,我选用了 Jmeter 进行测试,测试其连接数.发布订阅数据指标 二.测试环境搭建 1. Jmeter 2. Jmeter 插件:需要自行从插件管 ...