JAVA队列(Queue)用法附实例讲解

news/2024/4/25 23:35:09/文章来源:https://blog.csdn.net/xy666999/article/details/130320967

队列是什么

队列用于模拟队列这种数据结构,队列通常是指“先进先出”的容器。新元素插入(offer)到队列的尾部,访问元素(poll)操作会返回队列头部的元素。通常,队列不允许随机访问队列中的元素

Queue的6个方法

压入元素(添加):add()、offer()
相同:未超出容量,从队尾压入元素,返回压入的那个元素。
区别:在超出容量时,add()方法会对抛出异常,offer()返回false

弹出元素(删除):remove()、poll()
相同:容量大于0的时候,删除并返回队头被删除的那个元素。
区别:在容量为0的时候,remove()会抛出异常,poll()返回false

获取队头元素(不删除):element()、peek()
相同:容量大于0的时候,都返回队头元素。但是不删除。
区别:容量为0的时候,element()会抛出异常,peek()返回null。

队列的UML类图

类图UML

Queue的分类

在这里插入图片描述

阻塞队列

阻塞队列(Blocking Queue)提供了可阻塞的 put 和 take 方法,它们与可定时的 offer 和 poll 是等价的。如果队列满了 put 方法会被阻塞等到有空间可用再将元素插入;如果队列是空的,那么take 方法也会阻塞,直到有元素可用。当队列永远不会被充满时,put 方法和 take 方法就永远不会阻塞。

public class BlockingQueue {public static void main(final String[] args) {final ArrayBlockingQueue queue = new ArrayBlockingQueue(5);Thread thread1 = new Thread(){@Overridepublic void run() {for (int i = 0; i < 10; i++) {try {queue.put(i);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(new Date() + " | ArrayBlockingQueue Size:" + queue.size());}System.out.println(new Date() + " | For End.");}};thread1.start();new Thread(()->{for (int i = 0; i < 5; i++) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}if(!queue.isEmpty()){try {queue.take();} catch (InterruptedException e) {e.printStackTrace();}}}}).start();}
}

非阻塞队列

非阻塞队列也就是普通队列,它的名字中不会包含 BlockingQueue 关键字,并且它不会包含 put 和 take 方法,当队列满之后如果还有新元素入列会直接返回错误,并不会阻塞的等待着添加元素,如下图所示:
在这里插入图片描述
非阻塞队列的典型代表是 ConcurrentLinkedQueue 和PriorityQueue。

有界队列

有界队列:是指有固定大小的队列,比如设定了固定大小的 ArrayBlockingQueue,又或者大小为 0 的 SynchronousQueue。
在这里插入图片描述

无界队列

无界队列:指的是没有设置固定大小的队列,但其实如果没有设置固定大小也是有默认值的,只不过默认值是 Integer.MAX_VALUE,当然实际的使用中不会有这么大的容量(超过 Integer.MAX_VALUE),所以从使用者的角度来看相当于 “无界”的。

在这里插入图片描述

普通队列

普通队列(Queue)是指实现了先进先出的基本队列,例如 ArrayBlockingQueue 和 LinkedBlockingQueue,其中

ArrayBlockingQueue是用数组实现的普通队列,如下图所示
在这里插入图片描述
而 LinkedBlockingQueue 是使用链表实现的普通队列,如下图所示:
在这里插入图片描述
注意:一般情况下 offer() 和 poll() 方法配合使用,put() 和 take() 阻塞方法配合使用,add() 和 remove() 方法会配合使用,程序中常用的是 offer() 和 poll() 方法,因此这两个方法比较友好,不会报错。

public class BlockingQueue {public static void main(final String[] args) {LinkedBlockingQueue queue = new LinkedBlockingQueue(2);queue.offer("Hello");queue.offer("Java");queue.offer("中文社群");while (!queue.isEmpty()) {System.out.println(queue.poll());}}

双端队列

双端队列(Deque)是指队列的头部和尾部都可以同时入队和出队的数据结构,如下图所示:
在这里插入图片描述
java.util.concurrent 包里的 BlockingDeque 接口表示一个线程安放入和提取实例的双端队列。

BlockingDeque 类是一个双端队列,在不能够插入元素时,它将阻塞住试图插入元素的线程;在不能够抽取元素时,它将阻塞住试图抽取的线程。 deque(双端队列) 是 “Double Ended Queue” 的缩写。因此,双端队列是一个你可以从任意一端插入或者抽取元素的队列。

在线程既是一个队列的生产者又是这个队列的消费者的时候可以使用到 BlockingDeque。如果生产者线程需要在队列的两端都可以插入数据,消费者线程需要在队列的两端都可以移除数据,这个时候也可以使用 BlockingDeque。BlockingDeque 图解:
在这里插入图片描述
BlockingDeque 的方法
一个 BlockingDeque - 线程在双端队列的两端都可以插入和提取元素。 一个线程生产元素,并把它们插入到队列的任意一端。如果双端队列已满,插入线程将被阻塞,直到一个移除线程从该队列中移出了一个元素。如果双端队列为空,移除线程将被阻塞,直到一个插入线程向该队列插入了一个新元素。

在这里插入图片描述

public class BlockingQueue {public static void main(final String[] args) {// 创建一个双端队列LinkedBlockingDeque deque = new LinkedBlockingDeque();deque.offer("offer"); // 插入首个元素deque.offerFirst("offerFirst"); // 队头插入元素deque.offerLast("offerLast"); // 队尾插入元素while (!deque.isEmpty()) {// 从头遍历打印System.out.println(deque.poll());}}
offerFirst
offer
offerLast

优先队列

优先队列(PriorityQueue)是一种特殊的队列,它并不是先进先出的,而是优先级高的元素先出队,内部基于数组实现,线程不安全的队列
使用优先队列时应规定排序规则(需要在类里实现Comparable接口,或自己写一个实现Comparator接口的类)

public class BlockingQueue {public static void main(final String[] args) {PriorityQueue queue = new PriorityQueue<>(10,new Comparator<Student>(){@Overridepublic int compare(Student v1, Student v2) {//按照level倒序取出return v2.getLevel() - v1.getLevel();}});queue.offer(new Student(1,"a",5));queue.offer(new Student(1,"a",1));queue.offer(new Student(1,"a",3));while(!queue.isEmpty()) {System.out.println(queue.poll().toString());}}@Dataprivate static class Student {private int id;private String name;private int level;public Student(int id, String name, int level) {this.id = id;this.name = name;this.level = level;}}}BlockingQueue.Student(id=1, name=a, level=5)
BlockingQueue.Student(id=1, name=a, level=3)
BlockingQueue.Student(id=1, name=a, level=1)

其他队列

在 Java 的队列中有一个比较特殊的队列 SynchronousQueue,它的特别之处在于它内部没有容器,每次进行 put() 数据后(添加数据),必须等待另一个线程拿走数据后才可以再次添加数据,它的使用示例如下:

public class SynchronousQueueTest {public static void main(String[] args) {SynchronousQueue queue = new SynchronousQueue();// 入队new Thread(() -> {for (int i = 0; i < 3; i++) {try {System.out.println(new Date() + ",元素入队");queue.put("Data " + i);} catch (InterruptedException e) {e.printStackTrace();}}}).start();// 出队new Thread(() -> {while (true) {try {Thread.sleep(1000);System.out.println(new Date() + ",元素出队:" + queue.take());} catch (InterruptedException e) {e.printStackTrace();}}}).start();}
}
Wed Oct 20 01:54:52 CST 2021,元素入队
Wed Oct 20 01:54:53 CST 2021,元素出队:Data 0
Wed Oct 20 01:54:53 CST 2021,元素入队
Wed Oct 20 01:54:54 CST 2021,元素出队:Data 1
Wed Oct 20 01:54:54 CST 2021,元素入队
Wed Oct 20 01:54:55 CST 2021,元素出队:Data 2

从上述结果可以看出,当有一个元素入队之后,只有等到另一个线程将元素出队之后,新的元素才能再次入队。

延迟队列

延迟队列(DelayQueue)是基于优先队列 PriorityQueue 实现的,它可以看作是一种以时间为度量单位的优先的队列,当入队的元素到达指定的延迟时间之后方可出队。

Queue使用场景

很典型的JDK自带的线程池中就大量使用了Queue来存储任务。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_102456.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MII、 RMII、 GMII、 RGMII 接口介绍

1、RGMII 接口概要 以太网的通信离不开物理层 PHY 芯片的支持&#xff0c;以太网 MAC 和 PHY 之间有一个接口&#xff0c;常用的接口有MII、 RMII、 GMII、 RGMII 等。 MII&#xff08;Medium Independent Interface&#xff0c; 媒体独立接口&#xff09;&#xff1a; MII 支持…

三闯港交所,主打性价比的乡村基如何夺魁“中式快餐第一股”?

曾被中金公司称为“中国大消费最燃赛道”的中式餐饮&#xff0c;正在密集掀起IPO的风潮。去年5月和7月&#xff0c;老乡鸡和老娘舅分别向上交所提交招股书&#xff0c;绿茶餐厅、杨国福麻辣烫、捞王等企业也在推进上市计划。 国内第四大中式快餐集团&#xff0c;占据约0.6%市场…

Linux 通过Chrony实现NTP

Linux实现NTP服务器时间同步&#xff0c;可以通过ntp服务实现&#xff0c;也可以通过chrony服务实现 两者区别主要有 Chrony运行于UDP的323端口&#xff0c;NTP运行于UDP的123端口 Chrony相比于NTP可以更快同步&#xff0c;能够最大同步的减少时间和频率的误差 Chrony能够更好…

考过HCIP入职心仪公司,分享华为认证学习经历及心得

我成功考过了HCIP&#xff0c;并通过HCIP技术拿下了3家心仪公司。 学习经历 考过或者了解过HCIP的朋友都知道&#xff0c;考试内容大多数是概念类的问题。因为我工作的缘故没有太多时间自学&#xff0c;所以我报了个线上培训班&#xff0c;这个我不建议大家盲目跟风&#xff0…

EEG源定位

导读 自从脑电图(EEG)被发现以来&#xff0c;人们希望EEG能提供一个了解大脑的窗口&#xff0c;研究人员一直试图用EEG无创定位大脑中产生头皮电位的神经元活动。20世纪50年代的早期探索使用电场理论从头皮电位分布推断大脑中电流偶极子的位置和方向&#xff0c;引发了大量定量…

第五章-数字水印-2-原理及实现

数字水印原理 根据之前图像获取位平面的操作可知&#xff0c;最低位位平面对整体图像的影响最小&#xff0c;因此数字水印的原理为在图像的最低有效位上嵌入隐藏信息&#xff0c;即在图像的最低位替换为数字水印位平面&#xff0c;完成数字的嵌入操作&#xff0c;对已嵌入数字…

【opencv】图像数字化——矩阵的运算( 5 乘法运算)

5 乘法运算 5.1使用“*”运算符 对于Mat对象的乘法&#xff0c;两个Mat只能同时是float或者double类型&#xff0c;对于其它数据类型的矩阵乘法会报错src1的列数等于src2的行数mn * npmp #include <opencv2/core/core.hpp> #include<iostream> using namesp…

实战iOS App 重签名

熟悉iOS开发的同学都知道,iOS应用的上架流程主要分为以下几步: 创建开发者账号借助辅助工具appuploader创建证书,描述文件iTunes connect创建App打包IPA上传App Store等待审核在签名的流程中,有一个App重签名的步骤,主要针对的是一些大公司有多个App的情况,多个App一个申…

数据库基础篇 《4. 运算符》

目录 1. 算术运算符 1&#xff0e;加法与减法运算符 2&#xff0e;乘法与除法运算符 3&#xff0e;求模&#xff08;求余&#xff09;运算符 2. 比较运算符 1&#xff0e;等号运算符 2&#xff0e;安全等于运算符 3&#xff0e;不等于运算符 4. 空运算符 5. 非空运算…

Unity 工具控件 之 Text 文本字间距调整(老版本的Unity编写工具控件/新版本Unity使用TMP)

Unity 工具控件 之 Text 文本字间距调整(老版本的Unity编写工具控件/新版本Unity使用TMP) 目录 Unity 工具控件 之 Text 文本字间距调整(老版本的Unity编写工具控件/新版本Unity使用TMP) 一、简单介绍 二、老版本 Unity Text 使用工具控件调整行间距 三、新版本 Unity Text…

站在程序猿的角度理解:UDP 协议

哈喽&#xff0c;大家好~我是你们的老朋友&#xff1a; 保护小周ღ&#xff0c;本期为大家带来的是 网络基础原理中的 UDP 协议&#xff0c;从什么协议&#xff1f;&#xff0c;认识 UDP 协议&#xff0c;UDP 的报文格式&#xff0c;UDP 传输大文件时的策略&#xff0c;以及 UD…

VS code 插件之中英文间自动添加空格

前言 不知道大家在开发过程中是不是会遇到写代码注释或者文本内容时中英文之间没有空格的情况&#xff0c;很多时候在写代码尤其是写注释的时候容易忘记加空格&#xff0c;但回过头来看又难以忍受&#xff0c;于是我就想着自己写一个 vscode 插件来解决这个问题&#xff0c;希…

展会邀请 | 虹科诚邀您4月26-28日前来参观成都国际工业博览会

HONGKE NEWS 2023 成都国际工业博览会精准聚焦中国智能制造&#xff0c;将通过展示自动化和工业机器人技术、新一代信息技术、金属加工、节能与工业配套、新材料等全行业最新技术和解决方案&#xff0c;完美呈现智能工业产业链中的创新技术及产品的有效融合。 2023年4月26日-…

高效编程----VSCode+ChatGPT插件

VSCode中使用ChatGPT插件 首先在VSCode中打开扩展面板&#xff0c;搜索ChatGPT&#xff0c;安装蓝色圈出插件&#xff0c;如图所示&#xff1a; 安装完成后&#xff0c;需要重启VSCode 注册账号&#xff0c;如图所示&#xff1a; 然后在ChatGPT对话框中输入信息即可使用&#…

Python 实验四 常用数据结构(1)

1.从键盘输入一个正整数列表&#xff0c;以一1结束&#xff0c;分别计算列表中奇数和偶数的和。 n int(input("请输入一个正整数&#xff1a;")) list [] while n ! -1:list.append(n)n int(input("请输入一个正整数&#xff1a;")) else:print("…

【Linux网络】部署YUM仓库及NFS服务

部署YUM仓库及NSF服务 一、YUM仓库1.1、YUM仓库概述1.2准备安装来源1.3在软件仓库加载非官方RPM包组1.4yum与apt 二、配置yam源与制作索引表2.1配置FTP源2.2配置国内在线yum源2.3在线源与本地源同时使用2.4建立软件包索引关系表的三种方法 三、nfs共享存储服务3.1安装软件&…

Django框架之创建项目、应用并配置数据库

django3.0框架创建项目、应用并配置数据库 创建项目 进入命令行 新建一个全英文的目录 进入目录 输入命令 django-admin startproject project 项目目录层级 查看当前目录层级 tree /f 目录文件说明 创建数据库 做一个学生管理系统做演示&#xff0c;使用navicat创建数据…

ML之DR:sklearn.manifold(流形学习和降维的算法模块)的简介、部分源码解读、案例应用之详细攻略

ML之DR&#xff1a;sklearn.manifold(流形学习和降维的算法模块)的简介、部分源码解读、案例应用之详细攻略 目录 sklearn.manifold的简介 sklearn.manifold(流形学习和降维的算法模块)的概述 外文翻译 sklearn.manifold的部分源码解读 sklearn.manifold的简介 sklearn.ma…

Bugku——应急加固1

来打一下bugku的应急加固靶场&#xff0c;靶场链接&#xff1a;https://ctf.bugku.com/ctfplus/detail/id/2.html 启动环境 1、JS劫持域名 直接访问ip地址&#xff0c;发现是xxx学院二手交易市场&#xff0c;随后被劫持跳转到了一个博客页面。 博客地址就是第一个flag&…

Android音视频开发-OpenGL ES正交投影实现方法

本文实例为大家分享了OpenGL ES正交投影展示的具体代码&#xff0c;供大家参考&#xff0c;具体内容如下 绘制正方形 在最开始绘制的六边形里面好像看起来挺容易的&#xff0c;也没有出现什么问题&#xff0c;接下来不妨忘记前面绘制六边形的代码&#xff0c;让我们按照自己的…