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队列的更多相关文章

  1. C#部分---特殊集合:stack栈集合、queue队列集合、哈希表集合。

    1.stack栈集合:又名 干草堆集合 栈集合 特点:(1)一个一个赋值 一个一个取值(2)先进后出实例化 初始化 Stack st = new Stack(); //添加元素用push st.Pus ...

  2. Scala学习笔记--集合类型Queue,Set

    补充知识:http://www.importnew.com/4543.html 正文开始 scala.collection.immutable scala.collection.mutable 队列Q ...

  3. Stack集合 Queue队列集合 Hashtable哈希表

    Stack集合 干草堆集合 栈集合 栈;stack,先进后出,一个一个赋值,一个一个取值,安装顺序来. 属性和方法 实例化 初始化 Stack st = new Stack(); 添加元素 个数 Co ...

  4. MSMQ学习笔记二——创建Message Queue队列

    一.创建Message Queue队列的主要流程 1.定义MQQUEUEPROPS 结构: 2.设置消息队列属性: 3.初始化MQQUEUEPROPS 结构: 4.调用MQCreateQueue创建队 ...

  5. 特殊集合 Stack Queue Hashtable

    //Stack    干草堆集合    栈集合      先进后出 Stack st = new Stack(); //实例化 初始化 st.Push(2); //添加元素 st.Push(6); s ...

  6. JavaSE笔记-集合

    Java集合大致可分为:List,Set,Map,Queue List:有序,可重复 Set:无序(输出和插入顺序不一定一致),不可重复 Map:映射关系,根据key去访问value Queue:队列 ...

  7. 进击的Python【第九章】:paramiko模块、线程与进程、各种线程锁、queue队列、生产者消费者模型

    一.paramiko模块 他是什么东西? paramiko模块是用python语言写的一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接. 先来个实例: import param ...

  8. Java Queue队列

    前言 Queue队列是一种特殊的线性表,它只允许在表的前端进行删除操作,而在表的后端进行插入操作,LinkedList类实现了Queue接口,因此我们可以把LinkedList当成Queue来用.  ...

  9. C#基础---Queue(队列)的应用

       Queue队列,特性先进先出. 在一些项目中我们会遇到对一些数据的Check,如果数据不符合条件将会把不通过的信息返回到界面.但是对于有的数据可能会Check很多条件,如果一个数据一旦很多条件不 ...

  10. 第19章 queue队列容器

    /* 第19章 queue队列容器 19.1 queue技术原理 19.2 queue应用基础 19.3 本章小结 */ // 第19章 queue队列容器 // 19.1 queue技术原理 // ...

随机推荐

  1. WAF Bypass 介绍与实战

    前言 WAF是英文"Web Application Firewall"的缩写,中文意思是"Web应用防火墙",也称为"网站应用级入侵防御系统" ...

  2. Docker自建仓库搭建记录

    https://blog.csdn.net/u011943534/article/details/81331231 https://blog.csdn.net/u013165156/article/d ...

  3. JavaScript是怎样实现继承的?

    一.是什么 继承(inheritance)是面向对象软件技术当中的一个概念. 如果一个类别B"继承自"另一个类别A,就把这个B称为"A的子类",而把A称为&qu ...

  4. 嵌入式Linux—输入子系统

    输入系统 常见的输入设备有键盘.鼠标.遥控杆.书写板.触摸屏等等,用户通过这些输入设备与Linux系统进行数据交换. 内核中怎样表示一个输入设备 // include/linux/input.h st ...

  5. chai 3D 之网格对象

    推荐:将 NSDT场景编辑器 加入你的3D开发工具链 介绍 网格对象是由三角形和顶点组成的形状   在 CHAI3D 中,多边形网格是定义多面体对象形状的顶点和三角形的集合.   顶点是一个位置以及其 ...

  6. 动手写了个简单版的ChatGPT的Java版客户端

    最近ChatGpt大火,我在年前申请过账号忘了下确实强大. 作为Java程序猿社畜就尝试写了个Java版本的简易版客户端. 源码地址:https://github.com/Grt1228/chatgp ...

  7. oracle to mogdb 迁移---mtk工具

    ## 一.MTK工具介绍--------- MTK–异构数据迁移工具 MTK全称为 Database Migration Toolkit,是一个可以将Oracle/DB2/MySQL/openGaus ...

  8. TouchableOpacity无效

    错误代码如下: <TouchableOpacity onPress={this.handleConfirmPress} activeOpacity={0.6} > <Text sty ...

  9. BUG: kernel NULL pointer dereference, address: 0000000000000008

    问题现象:有台实例是用于压测用的,只要是做TCP连接数压测时,连接数超过100多就会自动重启,各种日志里面看不到任何关于重启的报错 xxx云服务器供应商技术支持,后台工具检测到有panic迹象,但不确 ...

  10. [WinError 10061] 由于目标计算机积极拒绝,无法连接。- EnlightenGan运行

    在测试EnlightenGan时,可视化结果保存出现问题. 原因:调用visdom可视化,需要先打开visdom python -m visdom.server