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

news2024/11/18 1:36:03

队列是什么

队列用于模拟队列这种数据结构,队列通常是指“先进先出”的容器。新元素插入(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(){
            @Override
            public 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>(){
                    @Override
                    public 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());
        }
 
    }
 
    @Data
    private 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.coloradmin.cn/o/451777.html

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

相关文章

【JavaWeb】Servlet(崔老师版)

文章目录 1.概述1.1 JavaWeb三大组件1.2 Servlet作用 2.ServletConfig接口3.Servlet接口3.1 实现Servlet的方式3.2 Servlet生命周期 4.HttpServlet抽象类6.ServletContext5.1 概述5.2 获取ServletContext5.3 JavaWeb四大域对象5.4 获取应用初始化参数5.5 ServletContext获取资源…

【UML建模】时序图(Sequence Diagram)

文章目录 1.概述2.时序图的组成元素2.1.角色&#xff08;Actor&#xff09;2.2.实体和对象2.3.生命周期线&#xff08;Lifeline&#xff09;2.3.1.激活&#xff08;Activation&#xff09;2.3.2.消息&#xff08;Messages&#xff09;2.3.3.组合片段&#xff08;Fragments&…

learn C++ NO.1——命名空间域、输入输出、函数重载

前言 什么是C C&#xff08;c plus plus&#xff09;是一种计算机高级程序设计语言&#xff0c;由C语言扩展升级而产生&#xff0c;最早于1979年由本贾尼斯特劳斯特卢普在AT&T贝尔工作室研发。C语言是结构化和模块化的语言&#xff0c;适合处理较小规模的程序。对于复杂的…

Cache存储系统详解(全相联映射、直接映射、组相联映射、替换策略和性能计算)

1. 存储系统的层次结构 为了解决容量、速度和价格之间的矛盾&#xff0c;把各种不同存储容量&#xff0c;不同存取速度&#xff0c;不同价格的存储器&#xff0c;按照一定的体系结构组织起来&#xff0c;使所存放的程序和数据按层次分布在各存储器中&#xff0c;形成---多层次的…

读书笔记//《数据科学工程实践》

出版时间&#xff1a;2021年11月 副标题&#xff1a;用户行为分析、A/B实验、SQLFlow 作者们是一线互联网企业的数据科学家、数据分析师和算法工程师&#xff0c;主要就职于滴滴、部分就职于腾讯、快手等。 点评&#xff1a;神仙下凡布道。感谢大佬们的分享。本书让我领略了大厂…

小白也能看懂,解读数据中台

不同的企业对数据有不同的需求。企业数据应用不断更新迭代&#xff0c;企业的中台系统也需要不断变化。从数据处理与数据治理两个维度出发&#xff0c;可以设计一个解耦的数据中台体系架构。该数据中台体系架构具有一定的柔性&#xff0c;可按照企业应用需求进行组合&#xff0…

多语言(CurlPHPPHPsdkJAVAC#Python)调用阿里巴巴商品API接口

2月2日消息&#xff0c;《晚点LatePost》独家报道&#xff0c;阿里集团国内批发业务1688近期完成了一系列组织和业务调整。其中&#xff0c;原1688商贸发展中心和产地发展中心合并为1688商家发展中心&#xff0c;由原商贸发展中心总经理王强负责&#xff1b;1688新成立分销供应…

苹果天气应用专利获批,苹果Find My技术改变防丢技术走向

根据美国商标和专利局&#xff08;USPTO&#xff09;公示的清单&#xff0c;苹果近日获得了名为“用于管理天气信息的用户界面”专利&#xff0c;编号为 US 11630559 B2。 苹果在专利描述中表示&#xff0c;部分管理天气信息的技术复杂且效率低下&#xff0c;用户需要多次点击…

spring redis Sentinel 哨兵 原理

客户端选择 redis 常用的连接客户端 有三个 Jedis&#xff1a;是老牌的Redis的Java实现客户端&#xff0c;提供了比较全面的Redis命令的支持&#xff0c;Redisson&#xff1a;实现了分布式和可扩展的Java数据结构。Lettuce&#xff1a;高级Redis客户端&#xff0c;用于线程安…

el-table合计功能滚动条层级问题

问题描述 版本&#xff1a;2.15.13 el-table在使用合计功能及固定列功能的同时&#xff0c;由于固定列的结构是固定区域增加了div加上定位&#xff0c;用来盖住下面的内容。当使用了合计功能的时候滚动条的区域在el-table__body-wrapper会导致固定列区域下的滚动条被挡住&…

计算机网络三:运输层

一、运输层 1. 概述 运输层协议为运行在不同主机上的应用进程之间提供了逻辑通信功能&#xff0c;使得不同主机好像直接连在一起一样 运输层协议是在端系统中而不是在路由器中实现的。网络路由器仅作用于网络层分组(即数据报)的网络层字段&#xff0c;而不检查封装在该数据报…

微搭低代码学习之数据展示

低代码平台是一个快速发展的领域&#xff0c;未来有着广阔的发展前景。以下是一些低代码平台未来的发展方向&#xff1a; 1.人工智能和机器学习 随着人工智能和机器学习技术的不断发展&#xff0c;低代码平台将能够更好地利用这些技术来提高应用程序的智能化和自动化水平。例如…

APP渗透—绕过反代理、反证书检测

APP渗透—绕过反代理、反证书检测 1. 前言1.1. 无法获取数据包情况 2. 反代理2.1. 反代理情况2.1.1. 某牛牛反代理2.1.2. 某探反代理 2.2. 绕过反代理2.2.1. Proxifier设置2.2.1.1. 设置代理服务器2.2.1.2. 配置代理规则2.2.1.3. 检测状态 2.2.2. 抓包测试 2.3. 总结 3. 反证书…

用HTML+CSS简单的画一个支付宝页面(超详细)

&#x1f648;作者简介&#xff1a;练习时长两年半的Java up主 &#x1f649;个人主页&#xff1a;老茶icon &#x1f64a; ps:点赞&#x1f44d;是免费的&#xff0c;却可以让写博客的作者开兴好久好久&#x1f60e; &#x1f4da;系列专栏&#xff1a;Java全栈&#xff0c;计…

Pyqt实现合并PDF遇到的问题集合

1.exit code -1073740791报错 pycharm遇到如下报错&#xff1a; “Process finished with exit code -1073740791 (0xC0000409)” 就是遇到这种问题就不知道问题在哪里&#xff0c;有点摸不着头脑 解决措施&#xff1a; 1.点击导航栏“Run”后选择“Edit Configurations” …

Python机器学习、深度学习技术提升气象、海洋、水文领域实践应用

Python是功能强大、免费、开源&#xff0c;实现面向对象的编程语言&#xff0c;在数据处理、科学计算、数学建模、数据挖掘和数据可视化方面具备优异的性能&#xff0c;这些优势使得Python在气象、海洋、地理、气候、水文和生态等地学领域的科研和工程项目中得到广泛应用。可以…

Keil使用 fromelf 生成bin文件

一、语法格式如下&#xff1a; fromelf [options] input_file [options] 选项如下&#xff0c;可以组合使用&#xff0c;两者之间用空格隔开&#xff1a; 二、在Keil中的使用过程 1、配置Output&#xff0c;生成可执行文件 aa即为可执行文件名&#xff0c;后缀为axf。…

十三、51单片机之EEPROM(I2C)

1、EEPROM简介 (1)存储设备类型&#xff1a;ROM、RAM、PROM(可编程ROM)、EPROM(可擦除ROM)、EEPROM(电可擦除ROM)。 (2)为什么需要EEPROM&#xff1f; 某些数据内容我们需要掉电不丢失且在程序运行中可以修改这些数据内容&#xff0c;这就需要用到EEPROM。 (3)EEPROM和flas…

家庭智能开关通断—Homekit智能

智能通断器&#xff0c;也叫开关模块&#xff0c;可以非常方便地接入家中原有开关、插座、灯具、电器的线路中&#xff0c;通过手机App或者语音即可控制电路通断&#xff0c;轻松实现原有家居设备的智能化改造。 随着智能家居概念的普及&#xff0c;越来越多的人想将自己的家改…

Rust之泛型、特性和生命期(一):基本概念

开发环境 Windows 10Rust 1.69.0 VS Code 1.77.3 项目工程 这里继续沿用上次工程rust-demo 泛型、特性和生命期 每种编程语言都有有效处理概念重复的工具。在Rust中&#xff0c;一个这样的工具就是泛型&#xff1a;具体类型或其他属性的抽象替身。我们可以表达泛型的行为或…