当前位置: 首页 > article >正文

Java集合——Queue详解

Queue详解

  • 基本概念
  • 功能分类
  • 主要方法
    • 普通队列
    • 双端队列
    • 阻塞队列
  • 使用示例
  • 总结

基本概念

  • Java 中的 Queue 接口表示一种先进先出(FIFO, First In First Out)的数据结构,但实际上它也支持其他插入和删除策略。
  • Queue 是 Java 集合框架的一部分,它继承自 Collection 接口,并且定义了许多用于队列操作的方法。

功能分类

在这里插入图片描述

  • 双端队列:继承 Deque 接口的队列,支持从两端插入和移除元素。ArrayDequeLinkedList 都是 Deque 的实现类,可以用来创建栈或双端队列。

  • 阻塞队列:继承BlockingQueueBlockingDeque 接口的队列,当队列满或空时,插入或移除操作将会阻塞的队列。阻塞队列都是线程安全的。例如,ArrayBlockingQueueLinkedBlockingQueue 等。

  • 并发队列:在多线程环境中,使用普通的队列实现可能会导致数据不一致或竞争问题。Java 提供了线程安全的并发队列,ConcurrentLinkedQueueConcurrentLinkedDequeBlockingQueue

  • 有界队列:如 ArrayBlockingQueue 可以设置一个最大容量,当队列达到这个容量时,将不再接受新的元素插入,除非有其他元素被移除。

  • 无界队列:一些队列实现没有固定的容量限制,如 LinkedListArrayDeque

  • 优先队列PriorityQueuePriorityBlockingQueue ,根据元素的自然顺序或通过提供的 Comparator 来确定元素插入位置,队列内元素有序排列。当从队列中移除元素时,总是返回具有最高优先级的元素。

  • 延迟队列DelayQueue继承子 BlockingQueue,它允许元素在被添加时指定一个延迟时间。只有当这个延迟时间过去之后,元素才会变得可见。延迟队列中元素是按照延迟时间排序的,因此内部元素需要实现Delayed接口,其中compareTo方法,用于队列元素排序。延迟队列通常用于实现定时任务或事件调度等功能。

  • 同步队列SynchronousQueue 继承自 BlockingQueue,用于在线程之间直接传递元素。它没有内部缓冲区,也就是说它不能存储任何元素。因此,当一个线程试图向 SynchronousQueue 插入一个元素时(例如使用 put 方法),它会一直阻塞,直到另一个线程从队列中取出这个元素(例如使用 take 方法)。常用于生产者消费者模式。

主要方法

普通队列

操作抛出异常返回特殊值
插入add(e)offer(e)
删除remove()poll()
检查element()peek()

当队列为空或容量已满时,removeelementadd方法会抛出异常,而pollpeekoffer方法则会返回falsenull

双端队列

操作方法
尾部插入(队列)offer(e)
头部删除(队列)poll()
尾部插入(栈)push(e)
尾部删除(栈)pop()

既支持队列相关操作,也支持栈相关操作

阻塞队列

操作方法
插入put(e)
删除take()

阻塞队列中的puttake方法有阻塞特性,而offerpoll方法无阻塞特性,是非阻塞方法


使用示例

以下是一个使用 SynchronousQueue 的生产者消费者模式示例:

package leetcode.editor.cn;

import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;

public class SynchronousQueueExample {

    public static void main(String[] args) throws InterruptedException {
        /**
         * 创建一个非公平模式的 SynchronousQueue
         * 若队列中没有元素,当两个线程同时请求,优先插入操作
         * 若队列中已有元素,当两个线程同时请求,优先删除操作
         */
        SynchronousQueue<Integer> queue = new SynchronousQueue<>(false);

        Thread producerThread = new Thread(() -> {
            try {
                for (int i = 1; i <= 5; i++) {
                    System.out.println("Producer putting " + i);
                    queue.put(i);
                    TimeUnit.MILLISECONDS.sleep(100);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        Thread consumerThread = new Thread(() -> {
            try {
                for (int i = 1; i <= 5; i++) {
                    Integer value = queue.take();
                    System.out.println("Consumer taking " + value);
                    TimeUnit.MILLISECONDS.sleep(100);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        producerThread.start();
        consumerThread.start();
        
        producerThread.join();
        consumerThread.join();
    }
}

总结

实际常用的是LinkedListArrayDeque,既可以作为队列使用,也可以作为栈使用


http://www.kler.cn/a/299117.html

相关文章:

  • PostgreSQL中FIRST_VALUE、LAST_VALUE、LAG 和 LEAD是窗口函数,允许返回在数据集的特定窗口(或分区)内访问行的相对位置
  • 部署SenseVoice
  • 【centos8 镜像修改】centos8 镜像修改阿里云
  • e3 1220lv3 cpu-z分数
  • 【递归与回溯深度解析:经典题解精讲(下篇)】—— Leetcode
  • 【多维DP】力扣3366. 最小数组和
  • ActiveMQ 的网络连接及消息回流机制
  • Redis:处理缓存穿透的两种方法
  • web项目如何部署到服务器上并运行呢?——使用Tomcat插件
  • 数学建模笔记—— 蒙特卡罗法
  • 剖析Cookie的工作原理及其安全风险
  • git查看、修改、删除属性,配置提交commit用户名和邮箱
  • shiny 的认识和理解(必要)
  • 【JavaEE】TCP协议 (TCP-传输层协议 万字详解)
  • PHP轻松创建高效收集问卷调查小程序系统源码
  • 百度Apollo打通与ROS的通信,扩展自动驾驶系统生态
  • 8.10Laplacian算子
  • YOLO-v8:yolov8配置文件(yolov8.yaml)说明
  • 自用小问答
  • 分享一个基于微信小程序的医院挂号就诊一体化平台uniapp医院辅助挂号应用小程序设计(源码、调试、LW、开题、PPT)
  • qt通过调节伽马值来调节显示器亮度
  • oracle19.3单机升级到Oracle19.22
  • 主流无线物联网通信技术有哪些
  • 《一个操作系统的实现》--- ubuntu下bochs2.3.5的配置与使用
  • 大宗商品价格在二十多年中的时间序列变化趋势数据分析
  • 计算机毕业设计 家校互联管理系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试