【当年笔记】集合之Queue队列
1)Queue 分类
- 双端队列:双端队列(Deque)是 Queue 的子类也是 Queue 的补充类,头部和尾部都支持元素插入和获取。
- 阻塞队列:阻塞队列指的是指添加或删除元素时,如果没有成功,会阻塞并挂起等待,直到操作执行完成。
- 非阻塞队列:非阻塞队列指的是指添加或删除元素时,如果没有成功,会直接返回操作的结果。双端队列也属于非阻塞队列。
阻塞队列
1)BlockingQueue
常用方法
插入元素:
- add(E):添加元素到队尾,成功返回 true,失败抛出异常;
- offer(E):添加元素到队尾,成功返回 true,失败返回 false ;
- offer(E o,Long timeOut,Timme):添加元素到队尾,成功返回 true,失败返回 false ;
- put(E):添加元素到队尾,如果该队列已满,则一直阻塞。
移除元素: - remove(Object):移除指定元素,成功返回 true,失败返回 false;
- poll(): 获取并移除队列的首个元素,如果队列为空,则返回 null;
- take():获取并移除队列首个元素,如果队列尾空,则一直阻塞。
查看元素: - peek():获取但不移除队列的首个元素,若队列为空,则返回 null。
2)ArrayBlockingQueue
是一个有边界的阻塞队列,它的内部实现是一个数组。它的容量是有限的,我们必须在其初始化的时候指定它的容量大小,容量大小一旦指定就不可改变。
ArrayBlockingQueue 不允许元素为 null
这个类新增offer(E e, long timeout, TimeUnit unit)方法:添加失败后会等待一段时间,超时后返回false。
3)LinkedBlockingQueue
是一个由链表实现的有界阻塞队列,容量默认值为Integer.MAX_VALUE,也可以自定义容量,建议指定容量大小,默认大小在添加速度大于删除速度情况下有造成内存溢出的风险
4)DelayQueue
DelayQueue 是一个支持延时获取元素的无界阻塞队列,队列中的元素必须实现 Delayed接口,在创建元素时可以指定延迟时间,只有到达了延迟的时间之后,才能获取到该元素。
非阻塞队列
ConcurrentLinkedQueue是一个基于链接节点的无界线程安全队列。
优先级队列
PriorityQueue 一个基于优先级堆的无界优先级队列。可根据构造队列时提供的 Comparator排序,该队列不许有null。
- PriorityQueue 是非线程安全的,在多线程情况下可使用 PriorityBlockingQueue 类替代
1.ArrayBlockingQueue 和 LinkedBlockingQueue 的区别是什么?
ArrayBlockingQueue 和 LinkedBlockingQueue 都实现自阻塞队列
BlockingQueue,它们的区别主要体现在以下几个方面:
- ArrayBlockingQueue 使用时必须指定容量值,LinkedBlockingQueue 可以不用指定;
- ArrayBlockingQueue 的最大容量值是使用时指定的,并且指定之后就不允许修改;而 LinkedBlockingQueue 最大的容量为 Integer.MAX_VALUE;
- ArrayBlockingQueue 数据存储容器是采用数组存储的;而 LinkedBlockingQueue 采用的是 Node 节点存储的。
2.Java 中常见的阻塞队列有哪些?
答:Java 中常见的阻塞队列如下:
- ArrayBlockingQueue,由数组结构组成的有界阻塞队列;
- PriorityBlockingQueue,支持优先级排序的无界阻塞队列;
- SynchronousQueue,是一个不存储元素的阻塞队列,会直接将任务交给消费者,必须等队列中的添加元素被消费后才能继续添加新的元素;
- LinkedBlockingQueue,由链表结构组成的阻塞队列;
- DelayQueue,支持延时获取元素的无界阻塞队列
3.如何手动实现一个延迟消息队列?
可以用DelayQueue延迟队列来解决这个问题。实现思路,消息队列分为生产者和消费者,生产者用于增加消息,消费者用于获取并消费消息,我们只需要生产者把消息放入到DelayQueue 队列并设置延迟时间,消费者循环使用 take() 阻塞获取消息即可。完整的实现代码如下:
public class CustomDelayQueue {
// 消息编号
static AtomicInteger MESSAGENO = new AtomicInteger(1);
public static void main(String[] args) throws InterruptedException {
DelayQueue<DelayedElement> delayQueue = new DelayQueue<>();
// 生产者1
producer(delayQueue, "生产者1");
// 生产者2
producer(delayQueue, "生产者2");
// 消费者
consumer(delayQueue);
}
//生产者
private static void producer(DelayQueue<DelayedElement> delayQueue, String name) {
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
// 产生 1~5 秒的随机数
long time = 1000L * (new Random().nextInt(5) + 1);
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 组合消息体
String message = String.format("%s,消息编号:%s 发送时间:%s 延迟:%s 秒",
name, MESSAGENO.getAndIncrement(), DateFormat.getDateTimeInstance().format(new Date()), time / 1000);
// 生产消息
delayQueue.put(new DelayedElement(message, time));
}
}
}).start();
}
//消费者
private static void consumer(DelayQueue<DelayedElement> delayQueue) {
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
DelayedElement element = null;
try {
// 消费消息
element = delayQueue.take();
System.out.println(element);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
// 延迟队列对象
static class DelayedElement implements Delayed {
// 过期时间(单位:毫秒)
long time = System.currentTimeMillis();
// 消息体
String message;
// 参数:delayTime 延迟时间(单位毫秒)
public DelayedElement(String message, long delayTime) {
this.time += delayTime;
this.message = message;
}
@Override
// 获取过期时间
public long getDelay(TimeUnit unit) {
return unit.convert(time - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
@Override
// 队列元素排序
public int compareTo(Delayed o) {
if (this.getDelay(TimeUnit.MILLISECONDS) > o.getDelay(TimeUnit.MILLISECONDS))
return 1;
else if (this.getDelay(TimeUnit.MILLISECONDS) < o.getDelay(TimeUnit.MILLISECONDS))
return -1;
else
return 0;
}
@Override
public String toString() {
// 打印消息
return message + " |执行时间:" + DateFormat.getDateTimeInstance().format(new Date());
}
}
}
以上程序支持多生产者,执行的结果如下:
> 生产者1,消息编号:1 发送时间:2019-6-12 20:38:37 延迟:2 秒 |执行时间:2019-6-12 20:38:39
>
> 生产者2,消息编号:2 发送时间:2019-6-12 20:38:37 延迟:2 秒 |执行时间:2019-6-12 20:38:39
>
> 生产者1,消息编号:3 发送时间:2019-6-12 20:38:41 延迟:4 秒 |执行时间:2019-6-12 20:38:45
>
> 生产者1,消息编号:5 发送时间:2019-6-12 20:38:43 延迟:2 秒 |执行时间:2019-6-12 20:38:45
【当年笔记】集合之Queue队列的更多相关文章
- C#部分---特殊集合:stack栈集合、queue队列集合、哈希表集合。
1.stack栈集合:又名 干草堆集合 栈集合 特点:(1)一个一个赋值 一个一个取值(2)先进后出实例化 初始化 Stack st = new Stack(); //添加元素用push st.Pus ...
- Scala学习笔记--集合类型Queue,Set
补充知识:http://www.importnew.com/4543.html 正文开始 scala.collection.immutable scala.collection.mutable 队列Q ...
- Stack集合 Queue队列集合 Hashtable哈希表
Stack集合 干草堆集合 栈集合 栈;stack,先进后出,一个一个赋值,一个一个取值,安装顺序来. 属性和方法 实例化 初始化 Stack st = new Stack(); 添加元素 个数 Co ...
- MSMQ学习笔记二——创建Message Queue队列
一.创建Message Queue队列的主要流程 1.定义MQQUEUEPROPS 结构: 2.设置消息队列属性: 3.初始化MQQUEUEPROPS 结构: 4.调用MQCreateQueue创建队 ...
- 特殊集合 Stack Queue Hashtable
//Stack 干草堆集合 栈集合 先进后出 Stack st = new Stack(); //实例化 初始化 st.Push(2); //添加元素 st.Push(6); s ...
- JavaSE笔记-集合
Java集合大致可分为:List,Set,Map,Queue List:有序,可重复 Set:无序(输出和插入顺序不一定一致),不可重复 Map:映射关系,根据key去访问value Queue:队列 ...
- 进击的Python【第九章】:paramiko模块、线程与进程、各种线程锁、queue队列、生产者消费者模型
一.paramiko模块 他是什么东西? paramiko模块是用python语言写的一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接. 先来个实例: import param ...
- Java Queue队列
前言 Queue队列是一种特殊的线性表,它只允许在表的前端进行删除操作,而在表的后端进行插入操作,LinkedList类实现了Queue接口,因此我们可以把LinkedList当成Queue来用. ...
- C#基础---Queue(队列)的应用
Queue队列,特性先进先出. 在一些项目中我们会遇到对一些数据的Check,如果数据不符合条件将会把不通过的信息返回到界面.但是对于有的数据可能会Check很多条件,如果一个数据一旦很多条件不 ...
- 第19章 queue队列容器
/* 第19章 queue队列容器 19.1 queue技术原理 19.2 queue应用基础 19.3 本章小结 */ // 第19章 queue队列容器 // 19.1 queue技术原理 // ...
随机推荐
- 线程基础知识10-volatile
1 简介 Volatile保证了可见性和有序性,没有保证原子性. 1.1 保证可见性简介 可见性就是指当一个线程修改了共享变量的值时,其他线程能够立即得知这个修改.volatile变量做到了这一点. ...
- 使用花生壳进行内网穿透实验SQLserver
在一次编写软件的过程中,想让远在河南的同学对试一试,但是他的电脑上没有与之对应的SQL数据库不能便不能够运行软件.于是我想到了远程连接.在使用花生壳的时候,遇到了一些问题,然而网络上并没有与之对应的解 ...
- JZOJ 【2021.11.10NOIP提高组联考】
简要题解 这套题比较 \(H_2O\) 建议题目背景美文共赏 \(\text{T1}\) 显然一个 \(O(n^3)\) 不能过的 \(dp\) 然而过了?! 用心在该卡时间的地方卡一卡 \(\tex ...
- 2020.11.30【NOIP提高A组】模拟
总结与反思 很不幸,估分 \(170\),可惜 \(T2\) 暴力 \(50pts\) 全掉了 \(T1\) 结论题,如果想到了,\(O(n)\) 过,只有十几行代码 感觉不好想,不过还是 \(A\) ...
- 组织炎症水平高的RA患者接受TNF拮抗剂治疗的效果更好
组织炎症水平高的RA患者接受TNF拮抗剂治疗的效果更好van der Pouw Kraan TC, et al. Ann Rheum Dis. 2008;67(4):563-6.目的:不同患者对TNF ...
- K3S 系列文章-RHEL7.8 离线有代理条件下安装 K3S
一 基础信息 1.1 前提 本次安装的为 k3s 1.21.7+k3s1 VM 版本为 RHEL 7.8, 7.9 或 8.2, 8.3, 8.4(K3s 官网要求) VM YUM 仓库:已配置对应版 ...
- JMeter BeanShell 学习
JMeter BeanShell 学习 Beanshell分为: JMeter有如下BeanShell组件: 定时器: BeanShell Timer 前置处理器:BeanShell PreProce ...
- because another server process exited abnormally and possibly corrupted shared memory
一.环境 系统平台:Linux x86-64 Red Hat Enterprise Linux 7 版本:4.1.1 二.症状 Red Hat 7.2操作系统部署HGDB 4.1.1后,日志经常出 ...
- xr32f429开发环境搭建
XR32是全志科技的一款MCU芯片,基本参数如下所示: 环境的搭建首先是下载芯片对应的资料和手册(QQ群723687715)软硬件资料 官网工具下载:注册全志服务平台 下载无线连接工具和无线MCU 工 ...
- AOP中的一些重要术语简介
AOP的定义:AOP(Aspect Oriented Progamming)利用称为"横切"的技术,剖解开封装的对象内部,把多个类的公共行为封装到一个可重用模块中,便于减少重复代码 ...