文章目录
- 前言
- 一、队列使用:
- 二、队列元素的存入:
- 三、队列元素的取出:
- 三、队列数据实现类:
- 非并发安全的队列:
- 并发安全的队列:
- 总结
前言
在 Java 中,队列(Queue)是一种用于存储和管理元素的线性数据结构,遵循先进先出(FIFO)的原则,即最先进入队列的元素最先被取出。Java 中提供了多种队列的实现类,常用的包括 LinkedList、ArrayDeque 和 PriorityBlockingQueue 等。。
一、队列使用:
以下是 Java 中队列的基本操作示例:
// 创建队列对象:
Queue<Integer> queue = new LinkedList<>(); // 使用 LinkedList 实现队列
Queue<Integer> queue = new ArrayDeque<>(); // 使用 ArrayDeque 实现队列
Queue<Integer> queue = new PriorityBlockingQueue<>(); // 使用 PriorityBlockingQueue 实现优先级队列
//入队操作(添加元素到队列尾部):
queue.offer(1); // 添加元素到队列尾部
queue.add(2);
queue.offer(3);
//出队操作(从队列头部取出元素):
int element = queue.poll(); // 移除并返回队列头部元素
int element = queue.remove(); // 移除并返回队列头部元素,如果队列为空则抛出异常
int element = queue.peek(); // 返回队列头部元素但不移除,如果队列为空则返回 null
//判断队列是否为空:
boolean isEmpty = queue.isEmpty(); // 判断队列是否为空
//查看队列元素个数:
int size = queue.size(); // 查看队列中元素个数
队列的使用可以帮助解决很多实际问题,例如任务调度、消息队列、缓冲等。开发人员在编写应用程序时,可以根据具体场景选择合适的队列实现类,并运用队列的操作来实现所需的功能。
二、队列元素的存入:
在 Java 中,添加元素到队列中的方法主要有 add()
、offer()
和 put()
,它们都用于将元素添加到队列中,但在处理队列已满情况时有一些区别。
-
add()
方法:- 语法:
boolean add(E e)
- 功能:将指定元素添加到队列的尾部
- 特点:如果队列已满,直接调用
add()
方法会抛出IllegalStateException
异常
- 语法:
-
offer()
方法:- 语法:
boolean offer(E e)
- 功能:将指定元素添加到队列的尾部
- 特点:如果队列已满,
offer()
方法会返回 false,不会抛出异常
- 语法:
-
put()
方法:- 语法:
void put(E e) throws InterruptedException
- 功能:将指定元素添加到队列的尾部
- 特点:如果队列已满,
put()
方法会阻塞当前线程,直到队列有足够的空间添加元素或者线程被中断,抛出 InterruptedException
- 语法:
总结:
add()
方法在队列已满时会直接抛出异常,不适合用于处理队列满的情况。offer()
方法在队列已满时会返回 false,可以通过判断返回值来处理队列满的情况。put()
方法在队列已满时会阻塞当前线程,适合用于处理队列满时的等待和阻塞情况,可以保证数据的插入成功。
开发人员根据具体的业务需求和处理逻辑,可以根据需要选择合适的方法来向队列中添加元素。如果需要避免出现队列满的情况导致异常,可以使用offer()
方法并根据返回值来进行处理。如果需要确保数据一定会被插入,可以使用 put()
方法来实现阻塞等待。
三、队列元素的取出:
在 Java 中,取出队列元素的方法主要有 poll()
、remove()
、peek()
和 take()
,它们用于从队列中获取并移除元素或者查看队列头部的元素,它们之间的区别如下:
-
poll()
方法:- 语法:
E poll()
- 功能:获取并移除队列头部的元素,如果队列为空则返回 null
- 特点:当队列为空时,返回 null,不会抛出异常
- 语法:
-
remove()
方法:- 语法:
E remove()
- 功能:获取并移除队列头部的元素,如果队列为空则抛出
NoSuchElementException
异常 - 特点:当队列为空时,会抛出异常
- 语法:
-
peek()
方法:- 语法:
E peek()
- 功能:查看但不移除队列头部的元素,如果队列为空则返回 null
- 特点:仅仅只是查看队首元素,并不对队首元素进行删除操作
- 语法:
-
take()
方法:- 语法:
E take() throws InterruptedException
- 功能:获取并移除队列头部的元素,如果队列为空会阻塞当前线程,直到有元素可以被取出或者线程被中断
- 特点:当队列为空时,会使当前线程进入阻塞状态,直到有元素可以被取出或者线程被中断
- 语法:
总结:
poll()
方法在队列为空时返回 null,无需处理异常。remove()
方法在队列为空时会抛出异常,需要对异常进行处理。peek()
方法用于查看队列头部元素但不移除,不会对队列产生影响。take()
方法在队列为空时会阻塞当前线程,适用于需要等待队列有元素可取时。
根据具体业务需求和处理逻辑,开发人员可以选择合适的方法来从队列中取出元素。如果需要防止异常,可以使用poll()
方法并根据返回值来进行处理。如果需要确保有元素可取后再进行操作,可以使用take()
方法。
三、队列数据实现类:
在 Java 中,队列的实现类主要可以分为两类:非并发安全的队列和并发安全的队列。下面列举一些常见的队列实现类,并标注它们的并发安全性:
非并发安全的队列:
LinkedList
: 非并发安全,适合用作普通队列但不适合在多线程环境下使用。ArrayDeque
: 非并发安全,同样适合用作普通队列但不适合在多线程环境下使用。PriorityQueue
: 非并发安全,不适合在多线程环境下使用。
并发安全的队列:
ArrayBlockingQueue
:具有固定容量的有界阻塞队列,是并发安全的。LinkedBlockingQueue
:基于链表的阻塞队列,是并发安全的。PriorityBlockingQueue
:基于优先级堆的无界阻塞队列,是并发安全的。ConcurrentLinkedQueue
:基于非阻塞算法的无界队列,是并发安全的。BlockingQueue
、LinkedTransferQueue
、LinkedBlockingDeque
等java.util.concurrent
包中的队列都是并发安全的。
注意:虽然上述并发安全的队列实现类可以在多线程环境下安全使用,但在具体使用时仍需根据业务场景进行综合考虑和选择。
在多线程环境下,推荐使用 java.util.concurrent
包中提供的并发安全队列实现类,这些类已经考虑了线程安全性和高效性。如果在非多线程环境下使用队列,可以选择非并发安全的实现类,如 LinkedList
或 ArrayDeque
。
总结
Java 中的队列 (Queue) 是一种先进先出 (FIFO) 的数据结构,用于存储元素并按照它们被添加的顺序进行访问。常用的队列实现类有 LinkedList、ArrayDeque、PriorityQueue 等,同时在 java.util.concurrent 包中还提供了多种并发安全的队列实现类。
以下是关于 Java 队列的总结:
- 队列是一种线性数据结构,支持在队尾插入元素,对头删除元素。
- Queue 接口继承自 Collection 接口,定义了一系列操作队列的方法,如入队、出队、查看头元素等。
- 常用的队列实现类有 LinkedList、ArrayDeque、PriorityQueue 等,它们分别基于链表、数组和优先级堆实现。
- LinkedList 和 ArrayDeque 是非并发安全的队列实现类,适合单线程操作。
- PriorityQueue 是一个基于优先级堆的队列,元素可以按照自然顺序或自定义比较器进行排序。
- java.util.concurrent 包中提供了一系列并发安全的队列实现类,如 ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue、ConcurrentLinkedQueue 等,适合在多线程环境下使用。
- 阻塞队列是一种特殊的队列,支持在队列满或空时阻塞等待元素的插入或获取,可通过 put()、take()、offer()、poll() 方法实现。
- 队列在多线程编程中经常被用来实现生产者消费者模式,通过队列来平衡生产者和消费者之间的速度差异。
- 总的来说,队列是一种常用的数据结构,在 Java 中有多种实现类及并发安全的实现类可供选择,开发人员可以根据具体需求选择适合的队列类来实现功能。队列在处理任务排队、数据传输等场景下具有重要作用,是编程中常用的数据结构之一。