队列是一种先进先出(FIFO)的线性数据结构,类似于现实中的排队场景:元素从队尾入队,从队头出队,且遵循“先到先服务”的原则,在Java中,Queue接口是队列的顶层抽象,位于java.util包下,定义了队列的核心操作方法,如入队(offer/add)、出队(poll/remove)、查看队头元素(peek/element)等,需要注意的是,Queue接口继承自Collection接口,而Deque(双端队列)接口则扩展了Queue,允许在队列两端进行插入和删除操作,Java中实现队列的方式多样,不同实现适用于不同场景,本文将详细介绍几种常见的队列实现方式及其特点。

基于LinkedList的队列实现
LinkedList是Java中最基础的队列实现之一,它不仅实现了List接口,还实现了Deque接口,因此可直接作为队列使用,其底层基于双向链表结构,每个节点包含前驱指针、后继指针和当前元素,因此插入和删除操作的时间复杂度均为O(1),适合频繁增删的场景。
使用LinkedList作为队列时,核心方法包括:
offer(E e):将元素添加到队尾,成功返回true,队列容量有限时返回false(LinkedList无容量限制,故始终返回true);poll():移除并返回队头元素,队列为空时返回null;peek():返回队头元素但不移除,队列为空时返回null。
示例代码:
Queue<String> queue = new LinkedList<>();
queue.offer("A"); // 入队:A
queue.offer("B"); // 入队:A->B
String head = queue.poll(); // 出队:A,head="A"
String next = queue.peek(); // 查看队头:B,next="B"
LinkedList的优势在于动态扩容(无需预先指定容量),但频繁的节点对象创建可能带来轻微内存开销,适合元素数量不固定、增删操作频繁的场景。
基于ArrayDeque的高性能队列实现
ArrayDeque是Java提供的另一种队列实现,它基于动态数组结构,实现了Deque接口,既可作为队列(FIFO)使用,也可作为栈(LIFO)使用,相比LinkedList,ArrayDeque在内存使用上更高效(无需存储节点指针),且在头尾操作时性能更优(随机访问时间复杂度为O(1))。
ArrayDeque的扩容策略采用2倍扩容,初始容量默认为16,扩容时重新分配数组并复制元素,核心方法与LinkedList类似,但额外支持双端操作,如addFirst(E e)、addLast(E e)等。

示例代码:
Queue<Integer> deque = new ArrayDeque<>(); deque.add(1); // 入队:1 deque.add(2); // 入队:1->2 deque.addFirst(0); // 双端入队:0->1->2 Integer first = deque.pollFirst(); // 出队队头:0,first=0 Integer last = deque.pollLast(); // 出队队尾:2,last=1
ArrayDeque适用于需要高性能头尾操作的场景,且是非线程安全的,若在多线程环境中使用需额外同步处理。
PriorityQueue优先级队列实现
PriorityQueue是一种特殊的队列,它不严格遵循FIFO规则,而是根据元素的“优先级”决定出队顺序:优先级高的元素先出队(默认自然排序,可通过自定义Comparator指定排序规则),其底层基于小顶堆(或大顶堆)实现,插入和删除操作的时间复杂度为O(log n)。
使用PriorityQueue时,元素需实现Comparable接口,或在构造时传入Comparator,示例:
PriorityQueue<Integer> pq = new PriorityQueue<>(); // 默认小顶堆
pq.add(3); pq.add(1); pq.add(2);
while (!pq.isEmpty()) {
System.out.print(pq.poll() + " "); // 输出:1 2 3
}
PriorityQueue常用于需要按优先级处理的场景,如任务调度、 Huffman编码、Dijkstra算法等,但需要注意的是,它不是线程安全的,多线程环境下需使用PriorityBlockingQueue。
阻塞队列(BlockingQueue)的多线程安全实现
在多线程环境中,队列的线程安全是关键问题,Java并发包(java.util.concurrent)提供了BlockingQueue接口,它扩展了Queue,支持阻塞操作:当队列为空时,出队操作(如take())会阻塞当前线程;当队列满时,入队操作(如put())会阻塞,直到队列可用或线程被中断。

常用实现包括:
- ArrayBlockingQueue:基于数组的有界阻塞队列,需指定容量,公平性可配置(公平锁可避免线程饥饿);
- LinkedBlockingQueue:基于链表的可选有界阻塞队列,容量默认为Integer.MAX_VALUE,吞吐量通常高于ArrayBlockingQueue;
- PriorityBlockingQueue:支持优先级的无界阻塞队列,内部使用堆结构,适合多线程优先级任务场景。
示例(生产者-消费者模型):
BlockingQueue<String> queue = new LinkedBlockingQueue<>();
// 生产者线程
new Thread(() -> {
try {
queue.put("A"); // 阻塞直到队列有空间
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
// 消费者线程
new Thread(() -> {
try {
String data = queue.take(); // 阻塞直到队列有元素
System.out.println("Consumed: " + data);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
BlockingQueue是Java并发编程的核心组件,极大简化了多线程间的数据同步问题,广泛应用于线程池、消息队列等场景。
Java中实现队列的方式多样,选择时需结合场景需求:单线程环境下,ArrayDeque因高性能和低内存开销优先;需要频繁头尾操作可选LinkedList;优先级排序场景使用PriorityQueue;多线程环境则依赖BlockingQueue及其实现类,理解不同队列的底层原理和特性,能帮助开发者设计出更高效、更稳定的系统。













