在Java中,Queue
接口是java.util
包的一部分,继承自Collection
接口,用于在处理前保存元素。它遵循FIFO(先进先出)原则,但优先级队列和LIFO队列除外。以下是关于Java队列的超全面介绍:
1. Queue接口的基本方法
方法 | 描述 | 异常情况(失败时) | 返回特殊值(失败时) |
---|---|---|---|
add(e) |
添加元素到队列尾部 | IllegalStateException |
false |
offer(e) |
尝试添加元素(更适合有容量限制的队列) | - | false |
remove() |
移除并返回队首元素 | NoSuchElementException |
- |
poll() |
移除并返回队首元素(队列为空时返回null ) |
- | null |
element() |
返回队首元素(不移除) | NoSuchElementException |
- |
peek() |
返回队首元素(不移除,队列为空时返回null ) |
- | null |
2. 常用实现类
2.1 LinkedList
- 特点:实现了
Queue
和Deque
接口,支持双向队列操作。 - 适用场景:频繁插入/删除元素的场景。
Queue<String> queue = new LinkedList<>();
queue.offer("A");
queue.offer("B");
System.out.println(queue.poll()); // 输出: A
2.2 PriorityQueue
- 特点:基于优先级堆实现,元素按自然顺序或指定比较器排序。
- 注意:不允许
null
元素,非线程安全。
Queue<Integer> priorityQueue = new PriorityQueue<>();
priorityQueue.offer(3);
priorityQueue.offer(1);
System.out.println(priorityQueue.poll()); // 输出: 1(最小元素优先)
2.3 ArrayDeque
- 特点:动态数组实现的双端队列,不允许
null
元素。 - 优势:无容量限制,比
LinkedList
在队列操作上更高效。
Deque<String> deque = new ArrayDeque<>();
deque.offerFirst("A");
deque.offerLast("B");
System.out.println(deque.pollLast()); // 输出: B
2.4 ConcurrentLinkedQueue
- 特点:基于链表的无界线程安全队列,采用CAS(Compare-and-Swap)操作。
- 适用场景:高并发环境。
Queue<String> concurrentQueue = new ConcurrentLinkedQueue<>();
concurrentQueue.offer("Task1");
concurrentQueue.poll(); // 线程安全操作
2.5 BlockingQueue接口及实现类
用于线程间通信,支持阻塞操作(如put()
和take()
)。
ArrayBlockingQueue
:有界数组实现的阻塞队列。LinkedBlockingQueue
:可选有界的链表阻塞队列。PriorityBlockingQueue
:支持优先级的无界阻塞队列。DelayQueue
:延迟元素的无界阻塞队列,元素必须实现Delayed
接口。
BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(10);
blockingQueue.put("Item"); // 队列满时阻塞
String item = blockingQueue.take(); // 队列空时阻塞
3. 双端队列(Deque)
Deque
接口继承自Queue
,支持两端元素插入和删除。
- 常用方法:
addFirst(e)
/offerFirst(e)
addLast(e)
/offerLast(e)
removeFirst()
/pollFirst()
removeLast()
/pollLast()
getFirst()
/peekFirst()
getLast()
/peekLast()
Deque<Integer> deque = new ArrayDeque<>();
deque.push(1); // 等价于 addFirst()
deque.push(2);
System.out.println(deque.pop()); // 输出: 2(LIFO栈操作)
4. 队列与线程安全
- 非线程安全队列:
LinkedList
、PriorityQueue
、ArrayDeque
。 - 线程安全队列:
ConcurrentLinkedQueue
:非阻塞线程安全队列。BlockingQueue
及其实现类:阻塞线程安全队列。
示例:生产者-消费者模式
BlockingQueue<Integer> queue = new LinkedBlockingQueue<>();
// 生产者线程
new Thread(() -> {
try {
queue.put(1);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
// 消费者线程
new Thread(() -> {
try {
Integer item = queue.take();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
5. 队列的应用场景
- 消息队列:实现异步处理(如RabbitMQ、Kafka)。
- 任务调度:按顺序执行任务。
- 广度优先搜索(BFS):使用队列存储待处理节点。
- 缓存淘汰策略:FIFO缓存(如
LinkedHashMap
的removeEldestEntry
方法)。
6. 注意事项
- 避免
null
元素:多数队列实现不允许null
,PriorityQueue
和ConcurrentLinkedQueue
会直接抛出异常。 - 容量限制:有界队列(如
ArrayBlockingQueue
)需处理满队列情况,避免阻塞或拒绝操作。 - 迭代器:队列的迭代器可能是弱一致性的,尤其是并发队列。
总结
队列类型 | 有序性 | 线程安全 | 有界性 | 适用场景 |
---|---|---|---|---|
LinkedList |
FIFO | 否 | 无界 | 灵活的双向队列操作 |
PriorityQueue |
优先级 | 否 | 无界 | 按优先级处理元素 |
ArrayDeque |
FIFO/LIFO | 否 | 动态扩容 | 高效的双端操作 |
ConcurrentLinkedQueue |
FIFO | 是 | 无界 | 高并发场景 |
ArrayBlockingQueue |
FIFO | 是 | 有界 | 固定容量的线程安全队列 |
DelayQueue |
延迟时间 | 是 | 无界 | 延迟任务调度 |
根据具体需求选择合适的队列实现,兼顾性能与线程安全。