简单易懂的Java Queue入门教程!

哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云;欢迎大家常来逛逛

  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。

  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。

小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!

前言

  在软件开发领域,队列是一种非常重要的数据结构。它被广泛应用于多线程、网络通信、缓存、消息队列等场景。Java语言提供了多种队列实现,其中最常用的是Queue接口及其实现类。下面将详细介绍Java中的Queue及其应用场景。

摘要

  本文将介绍Java中Queue接口及其实现类的概念、源代码解析、应用场景案例、优缺点分析、类代码方法介绍、测试用例等内容。原则上,读者需要掌握Java基础语法及数据结构相关知识。

Queue

简介

  Queue是Java中的一种接口,它继承自Collection接口,并添加了一些队列相关的方法。Queue的实现类有多种,包括LinkedList、ArrayBlockingQueue、PriorityQueue、ConcurrentLinkedQueue等。下面简要介绍一下各个实现类的特点:

  1. LinkedList

  LinkedList是Java中的一个双向链表实现类。LinkedList实现了Deque接口,Deque又是Queue接口的子接口,因此LinkedList可以被视为Queue的一种实现。LinkedList的优点是插入、删除操作效率高,但是随机访问效率低。

  1. ArrayBlockingQueue

  ArrayBlockingQueue是Java中的一个基于数组的有界阻塞队列实现类。它的内部实现类似于一个环形数组,数组的长度是固定的。ArrayBlockingQueue具有先进先出的队列特性,它支持多线程安全访问,可以指定等待时间,当队列满或空时,线程将被阻塞。

  1. PriorityQueue

  PriorityQueue是Java中的一个带优先级的队列实现类。它的内部是一个堆结构,根据元素的排序规则进行排序,每次出队时都会返回当前队列中最小(或最大)的元素。PriorityQueue的特点是插入、删除效率高,但是元素数量较大时遍历效率不高。

  1. ConcurrentLinkedQueue

  ConcurrentLinkedQueue是Java中的一个基于链表的无界并发队列实现类。ConcurrentLinkedQueue的特点是多线程安全,能够高效地处理高并发场景。它不支持阻塞操作,而且不保证元素的排序。

源代码解析

下面我们以ArrayBlockingQueue为例,简单解析一下它的源代码。

public class ArrayBlockingQueue<E> extends AbstractQueue<E>implements BlockingQueue<E>, java.io.Serializable {/** The queued items */final Object[] items;/** items index for next take, poll or remove */int takeIndex;/** items index for next put, offer, or add */int putIndex;/** Number of elements in the queue */int count;/** Main lock guarding all access */final ReentrantLock lock;/** Condition for waiting takes */private final Condition notEmpty;/** Condition for waiting puts */private final Condition notFull;// ...
}

  如上所示,ArrayBlockingQueue继承了AbstractQueue类,并实现了BlockingQueue接口和Serializable接口。其内部使用了一个Object数组items用于存储队列中的元素,使用takeIndex和putIndex分别表示下一次取出元素和添加元素的位置,使用count表示队列中当前元素个数,使用lock实现线程同步,使用notEmpty和notFull两个Condition实现阻塞和唤醒操作。

如下是部分源码截图:

在这里插入图片描述

应用场景案例

下面介绍一下Queue在实际开发中的应用场景:

  1. 消息队列

    在分布式系统中,消息队列是一种常用的通信方式。生产者向队列中添加消息,消费者从队列中取出消息进行处理。Java语言中提供的ActiveMQ和RabbitMQ等消息队列服务均使用了队列的相关技术。

  2. 线程池

    在Java中,线程池通常使用BlockingQueue来存储待执行的任务。当线程池中的线程已经全部分配任务时,新的任务将会被阻塞,直到有线程可用为止。Java中的ThreadPoolExecutor就是使用了BlockingQueue来存储待执行的任务。

  3. 缓存

  在Java中,缓存通常使用LinkedList或ConcurrentLinkedQueue来实现。缓存存储的是最近访问过的元素,当缓存已满时,新的元素会将最旧的元素移除。

优缺点分析

Queue的优缺点分析如下:

  1. 优点

    Queue能够高效地实现元素的插入、删除以及元素的存储。Queue还能够在多线程场景中安全地实现元素的读写操作。

  2. 缺点

  在某些场景下,Queue可能会存在性能瓶颈。例如当Queue中元素数量较大时,遍历操作效率较低,此时需要使用其他数据结构来优化性能。另外Queue中元素的顺序是固定的,无法对元素的顺序进行修改。

类代码方法介绍

Queue接口中包含了很多常用的方法,下面介绍一下其中一些常用的方法:

  1. add(E e)

    将元素e添加到队列尾部,如果队列已满,则抛出IllegalStateException异常。

  2. offer(E e)

    将元素e添加到队列尾部,返回值表示添加操作是否成功。

  3. remove()

    移除队列头部的元素并返回该元素,如果队列为空,则抛出NoSuchElementException异常。

  4. poll()

    移除队列头部的元素并返回该元素,如果队列为空,则返回null。

  5. element()

    返回队列头部的元素,如果队列为空,则抛出NoSuchElementException异常。

  6. peek()

    返回队列头部的元素,如果队列为空,则返回null。

测试用例

下面给出ArrayBlockingQueue的测试用例:

测试代码

package com.example.javase.collection;import java.util.concurrent.*;/*** @Author ms* @Date 2023-10-24 23:32*/
public class QueueTest {private static final int BUFFER_SIZE = 10;private static final int PRODUCER_COUNT = 5;private static final int CONSUMER_COUNT = 5;private static final int ITEM_COUNT = 1000;private static final ExecutorService pool = Executors.newCachedThreadPool();public static void main(String[] args) throws InterruptedException {ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>(BUFFER_SIZE);for (int i = 0; i < PRODUCER_COUNT; i++) {pool.execute(new Producer(queue, ITEM_COUNT));}for (int i = 0; i < CONSUMER_COUNT; i++) {pool.execute(new Consumer(queue, ITEM_COUNT));}TimeUnit.SECONDS.sleep(60);pool.shutdown();}static class Producer implements Runnable {final BlockingQueue<Integer> queue;final int count;Producer(BlockingQueue<Integer> queue, int count) {this.queue = queue;this.count = count;}public void run() {try {for (int i = 0; i < count; i++) {queue.put(i);}} catch (InterruptedException e) {Thread.currentThread().interrupt();}}}static class Consumer implements Runnable {final BlockingQueue<Integer> queue;final int count;Consumer(BlockingQueue<Integer> queue, int count) {this.queue = queue;this.count = count;}public void run() {try {for (int i = 0; i < count; i++) {queue.take();}} catch (InterruptedException e) {Thread.currentThread().interrupt();}}}
}

  这段代码实现了生产者-消费者模型,使用了Java内置的阻塞队列ArrayBlockingQueue来作为共享的缓冲区。主要包含了三个部分:

  1. 定义了共享缓冲区的大小BUFFER_SIZE、生产者和消费者的数量PRODUCER_COUNT和CONSUMER_COUNT,以及需要生产和消费的数据ITEM_COUNT。

  2. 在main方法中,创建一个ArrayBlockingQueue实例,并分别创建PRODUCER_COUNT个生产者线程和CONSUMER_COUNT个消费者线程,然后分别启动这些线程并等待60秒钟后关闭线程池。

  3. Producer和Consumer类都实现了Runnable接口。在Producer的run方法中,不断向队列中添加数据,直到添加的次数达到ITEM_COUNT;在Consumer的run方法中,不断从队列中取出数据,直到取出的次数达到ITEM_COUNT。由于ArrayBlockingQueue是线程安全的,因此不需要做额外的同步处理。

  总的来说,这段代码展示了如何使用Java内置的阻塞队列来实现生产者-消费者模型,避免了手动实现同步和互斥的复杂性,提高了代码的可读性、可维护性和可复用性。

测试结果

  根据如上测试用例,本地测试结果如下,仅供参考,你们也可以自行修改测试用例或者添加更多的测试数据或测试方法,进行熟练学习以此加深理解。

在这里插入图片描述

代码分析

  根据如上测试用例,本地测试结果如下,仅供参考,你们也可以自行修改测试用例或者添加更多的测试数据或测试方法,进行熟练学习以此加深理解。
  该代码是一个使用 ArrayBlockingQueue 实现的生产者-消费者模型的示例。包含一个主类 ArrayBlockingQueueTest 和两个内部静态类 Producer 和 Consumer。主类中创建一个 ArrayBlockingQueue,然后创建 PRODUCER_COUNTProducer 线程和 CONSUMER_COUNTConsumer 线程,并启动它们。每个 Producer 线程向队列中插入 ITEM_COUNT 个元素,每个 Consumer 线程从队列中取出 ITEM_COUNT 个元素。当所有线程运行完毕后,程序将等待 60 秒钟,然后关闭线程池。

  ProducerConsumer 类实现了 Runnable 接口,分别包含一个 BlockingQueue 对象和一个 count 变量。在 run() 方法中,Producer 线程将元素插入队列中,Consumer 线程从队列中取出元素。如果队列已满(对于 Producer)或者队列为空(对于 Consumer),线程会进入阻塞状态。如果线程被中断,则中断状态会被设置并退出线程。

  该示例使用了线程池来管理并发任务,增加效率。使用 ArrayBlockingQueue 实现了并发访问控制,保证了线程安全。

小结

  Queue是Java中的一个接口,它的实现类包括LinkedListArrayBlockingQueuePriorityQueueConcurrentLinkedQueue等。Queue常用于消息队列、线程池、缓存等场景。在使用Queue时需要注意线程安全性和性能问题。

总结

  本文介绍了Java中Queue接口及其实现类的概念、源代码解析、应用场景案例、优缺点分析、类代码方法介绍、测试用例等内容。Queue是Java中常用的数据结构,能够高效地实现元素的插入、删除及存储,在多线程场景中也能保障线程安全。常用的Queue实现类有LinkedList、ArrayBlockingQueue、PriorityQueue、ConcurrentLinkedQueue等,它们都具有各自的优缺点。Queue的应用场景包括消息队列、线程池、缓存等。在使用Queue时需要注意性能问题和线程安全性。

… …

文末

好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。

… …

学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!

wished for you successed !!!


⭐️若喜欢我,就请关注我叭。

⭐️若对您有用,就请点赞叭。

⭐️若有疑问,就请评论留言告诉我叭。

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

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

相关文章

如何建设智慧党校

随着信息技术的飞速展开&#xff0c;特别是近年移动互联网技术&#xff0c;物联网技术&#xff0c;人工智能技术&#xff0c;大数据数据的深入展开&#xff0c;我国快速的进入信息化社会&#xff0c;信息化对各行各业的改造越来越深入&#xff0c;任何职业&#xff0c;任何安排…

SSM【Spring SpringMVC Mybatis】—— Spring(一)

目录 1、初识Spring 1.1 Spring简介 1.2 搭建Spring框架步骤 1.3 Spring特性 1.5 bean标签详解 2、SpringIOC底层实现 2.1 BeanFactory与ApplicationContexet 2.2 图解IOC类的结构 3、Spring依赖注入数值问题【重点】 3.1 字面量数值 3.2 CDATA区 3.3 外部已声明be…

浅谈ArrayList和LinkedList的区别

ArrayList和LinkedList在Java中都是常用的List接口的实现类&#xff0c;但它们之间存在一些显著的区别。 实现方式&#xff1a; ArrayList&#xff1a;基于数组实现。内部使用一个动态数组来存储元素&#xff0c;这意味着可以通过索引快速访问元素&#xff0c;时间复杂度为O(1)…

算法学习笔记(Nim游戏)

N i m Nim Nim游戏 n n n堆物品&#xff0c;每堆有 a i a_i ai​个&#xff0c;每个玩家轮流取走任意一堆的任意个物品&#xff0c;但不能不取&#xff0c;取走最后一个物品的人获胜。 N i m Nim Nim游戏是一种经典的公平组合游戏。现在对它进行分析。 首先定义两个博弈中的状…

【Chisel】chisel中怎么处理类似verilog的可变位宽和parameter

在 Chisel 中处理可变位宽和参数的方式与 Verilog 有一些不同&#xff0c;因为 Chisel 是建立在 Scala 语言之上的。以下是如何在 Chisel 中处理这些概念的方法&#xff1a; 参数化&#xff08;Parameters&#xff09; 在 Chisel 中&#xff0c;参数化是通过在模块构造函数中定…

VUE使用饿了么的上传组件时实现图片预览

创作灵感 最近在写项目时&#xff0c;遇到了上传头像的需求&#xff0c;我使用的是element组件中的upload组件。但是在使用时&#xff0c;我需要实现预览、手动上传头像等功能。然而在使用饿了么组件时&#xff0c;这些功能还是需要我们自己去手动实现的&#xff0c;在手动实现…

Linux makefile进度条

语法 在依赖方法前面加上就不会显示这一行的命令 注意 1.make 会在当前目录下找名为“makefile” 或者 “Makefile” 的文件 2.为了生成第一依赖文件&#xff0c;如果依赖文件列表有文件不存在&#xff0c;则会到下面的依赖关系中查找 3..PHONY修饰的依赖文件总是被执行的 …

Redis——RDB、AOF和混合持久化机制

Redis提供了三种持久化机制来确保数据的持久保存&#xff0c;分别是RDB&#xff08;Redis DataBase&#xff09;、AOF&#xff08;Append Only File&#xff09;和混合持久化。 RDB&#xff08;Redis DataBase&#xff09; RDB持久化机制是将Redis在内存中的数据保存到磁盘上的…

xss-lab 1-18关payload

Less-1 ?name<script>alert()</script> Less-2 "><script>alert()</script> "οnclick"alert() " οnfοcus"alert() " οnblur"alert() Less-3 οnfοcusalert() οnbluralert() οnfοcusjavascript:aler…

Spring AopUtils深度解析:从入门到精通的全方位指南

1. 概述 AopUtils是Spring框架中的一个工具类&#xff0c;主要用于处理AOP&#xff08;面向切面编程&#xff09;相关的操作。它提供了一系列静态方法&#xff0c;帮助开发者更方便地处理AOP中的对象、代理以及通知&#xff08;Advice&#xff09;等。 2. 用途 AopUtils的主要…

操作系统原理与系统——实验十三多道批处理作业调度(作业可移动)

关键代码 #include<stdio.h> #include<stdlib.h> #include<string.h> typedef struct data{int hour;//当前小时int min;//当前分钟 }time; struct node{char name[20];//进程名time arrive;//到达就绪队列时间int zx;//执行时间(预期时间)int size;int ta…

Polygon市值机器人

随着区块链技术的蓬勃发展和数字货币市场的日益繁荣&#xff0c;投资者们对于如何精准把握市场动态、实现资产稳健增长的需求愈发迫切。在这个背景下&#xff08;市值管理飞//机//aishutuyu&#xff09;&#xff0c;Polygon市值机器人应运而生&#xff0c;作为一款基于Polygon公…

LeetCode 第397场周赛个人题解

目录 100296. 两个字符串的排列差 原题链接 思路分析 AC代码 100274. 从魔法师身上吸取的最大能量 原题链接 思路分析 AC代码 100281. 矩阵中的最大得分 原题链接 思路分析 AC代码 100312. 找出分数最低的排列 原题链接 思路分析 AC代码 100296. 两个字符串的排…

timerfd加epoll封装定时器

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 1、用timerfd加epoll封装定时器的优点2、代码实现 1、用timerfd加epoll封装定时器的优点 定时器为什么需要timerfd 在设计定时器时&#xff0c;我们首先想到的就是…

【SpringBoot】Redis Lua脚本实战指南:简单高效的构建分布式多命令原子操作、分布式锁

文章目录 一.Lua脚本1.Lua特性2.Lua优势 二.Lua语法1.注释2.变量3.数据类型&#xff1a;3.1.基本类型3.2.对象类型&#xff1a;表&#xff08;table&#xff09; 4.控制结构&#xff1a;4.1.条件语句: 使用if、else和elseif来实现条件分支。4.2.循环结构&#xff1a;Lua支持for…

Shell参数扩展形式学习笔记

Shell参数扩展形式学习笔记 文章目录 Shell参数扩展形式学习笔记空值判断处理 ${parameter:-word} ${parameter:word} ${parameter:?word} ${parameter:word}变量位置截取 ${parameter:offset} ${parameter:offset:length}变量匹配组合 ${!prefix*} ${!prefix} ${!name[]} ${!…

感知机和神经网络

引入 什么是神经网络&#xff1f; 我们今天学习的神经网络&#xff0c;不是人或动物的神经网络&#xff0c;但是又是模仿人和动物的神经网络而定制的神经系统&#xff0c;特别是大脑和神经中枢&#xff0c;定制的系统是一种数学模型或计算机模型&#xff0c;神经网络由大量的人…

图像处理:图像噪声添加

文章目录 前言一、高斯噪声二、椒盐噪声三、泊松噪声四、斑点噪声五、指数噪声六、均匀噪声总结 前言 本文主要介绍几种添加图像噪声的方法&#xff0c;用于数据增强等操作。 以下图为例。 一、高斯噪声 高斯噪声就是给图片添加一个服从高斯分布的噪声&#xff0c;可以通过调…

vLLM初探

vLLM是伯克利大学LMSYS组织开源的大语言模型高速推理框架&#xff0c;旨在极大地提升实时场景下的语言模型服务的吞吐与内存使用效率。vLLM是一个快速且易于使用的库&#xff0c;用于 LLM 推理和服务&#xff0c;可以和HuggingFace 无缝集成。vLLM利用了全新的注意力算法「Page…

Python+PySpark数据计算

1、map算子 对RDD内的元素进行逐个处理&#xff0c;并返回一个新的RDD&#xff0c;可以使用lambda以及链式编程&#xff0c;简化代码。 注意&#xff1a;再python中的lambda只能有行&#xff0c;如果有多行&#xff0c;要写成外部函数&#xff1b;&#xff08;T&#xff09;-&…