Ollama Java 中的队列(Queue)是常用的数据结构
·
Java 中的队列(Queue)是常用的数据结构,以下是详细的介绍和用法:
1. Queue 接口概述
Queue 接口是 Java Collections Framework 的一部分,继承自 Collection 接口,遵循先进先出(FIFO)原则。
2. 主要实现类
2.1 LinkedList
import java.util.LinkedList;
import java.util.Queue;
public class LinkedListQueueExample {
public static void main(String[] args) {
// 创建队列
Queue<String> queue = new LinkedList<>();
// 添加元素
queue.add("A"); // 可能抛出异常
queue.offer("B"); // 推荐使用,返回布尔值
System.out.println("队列: " + queue); // [A, B]
// 查看队首元素
System.out.println("队首元素: " + queue.element()); // A
System.out.println("队首元素: " + queue.peek()); // A
// 移除元素
String removed1 = queue.remove(); // 移除并返回A
String removed2 = queue.poll(); // 移除并返回B
System.out.println("移除的元素: " + removed1 + ", " + removed2);
System.out.println("队列是否为空: " + queue.isEmpty()); // true
}
}
2.2 PriorityQueue
import java.util.PriorityQueue;
import java.util.Queue;
public class PriorityQueueExample {
public static void main(String[] args) {
// 自然顺序(最小堆)
Queue<Integer> minHeap = new PriorityQueue<>();
minHeap.offer(5);
minHeap.offer(1);
minHeap.offer(3);
System.out.println("优先级队列(最小堆):");
while (!minHeap.isEmpty()) {
System.out.println(minHeap.poll()); // 1, 3, 5
}
// 自定义比较器(最大堆)
Queue<Integer> maxHeap = new PriorityQueue<>((a, b) -> b - a);
maxHeap.offer(5);
maxHeap.offer(1);
maxHeap.offer(3);
System.out.println("优先级队列(最大堆):");
while (!maxHeap.isEmpty()) {
System.out.println(maxHeap.poll()); // 5, 3, 1
}
}
}
2.3 ArrayDeque(双端队列)
import java.util.ArrayDeque;
import java.util.Deque;
public class ArrayDequeExample {
public static void main(String[] args) {
// 作为队列使用(FIFO)
Deque<String> queue = new ArrayDeque<>();
queue.offerLast("A");
queue.offerLast("B");
queue.offerLast("C");
System.out.println("队列操作:");
while (!queue.isEmpty()) {
System.out.println(queue.pollFirst()); // A, B, C
}
// 作为栈使用(LIFO)
Deque<String> stack = new ArrayDeque<>();
stack.offerFirst("A");
stack.offerFirst("B");
stack.offerFirst("C");
System.out.println("栈操作:");
while (!stack.isEmpty()) {
System.out.println(stack.pollFirst()); // C, B, A
}
}
}
3. 阻塞队列(BlockingQueue)
3.1 ArrayBlockingQueue
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
public class ArrayBlockingQueueExample {
public static void main(String[] args) throws InterruptedException {
BlockingQueue<String> queue = new ArrayBlockingQueue<>(3);
// 生产者线程
Thread producer = new Thread(() -> {
try {
queue.put("任务1");
queue.put("任务2");
queue.put("任务3");
System.out.println("生产者: 添加了3个任务");
// queue.put("任务4"); // 会阻塞,直到有空间
boolean success = queue.offer("任务4", 2, TimeUnit.SECONDS);
System.out.println("添加任务4: " + success);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
// 消费者线程
Thread consumer = new Thread(() -> {
try {
Thread.sleep(1000); // 等待生产者先添加任务
for (int i = 0; i < 4; i++) {
String task = queue.take();
System.out.println("消费者: 处理 " + task);
Thread.sleep(500);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
producer.start();
consumer.start();
producer.join();
consumer.join();
}
}
3.2 LinkedBlockingQueue
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class LinkedBlockingQueueExample {
public static void main(String[] args) {
// 无界队列(理论上有界,最大为Integer.MAX_VALUE)
BlockingQueue<Integer> unboundedQueue = new LinkedBlockingQueue<>();
// 有界队列
BlockingQueue<Integer> boundedQueue = new LinkedBlockingQueue<>(100);
// 生产消费示例
new Thread(() -> {
try {
for (int i = 1; i <= 5; i++) {
boundedQueue.put(i);
System.out.println("生产: " + i);
Thread.sleep(200);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
new Thread(() -> {
try {
for (int i = 0; i < 5; i++) {
Integer item = boundedQueue.take();
System.out.println("消费: " + item);
Thread.sleep(300);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
}
}
4. 并发队列
4.1 ConcurrentLinkedQueue
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ConcurrentLinkedQueueExample {
public static void main(String[] args) {
ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();
ExecutorService executor = Executors.newFixedThreadPool(3);
// 多个生产者
for (int i = 0; i < 2; i++) {
final int producerId = i;
executor.submit(() -> {
for (int j = 0; j < 3; j++) {
String item = "生产者" + producerId + "-任务" + j;
queue.offer(item);
System.out.println("添加: " + item);
}
});
}
// 消费者
executor.submit(() -> {
while (true) {
String item = queue.poll();
if (item != null) {
System.out.println("处理: " + item);
} else if (queue.isEmpty()) {
break;
}
}
});
executor.shutdown();
}
}
5. 延迟队列(DelayQueue)
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
class DelayedTask implements Delayed {
private final String name;
private final long startTime;
public DelayedTask(String name, long delayMillis) {
this.name = name;
this.startTime = System.currentTimeMillis() + delayMillis;
}
@Override
public long getDelay(TimeUnit unit) {
long diff = startTime - System.currentTimeMillis();
return unit.convert(diff, TimeUnit.MILLISECONDS);
}
@Override
public int compareTo(Delayed other) {
return Long.compare(this.startTime, ((DelayedTask) other).startTime);
}
@Override
public String toString() {
return "DelayedTask{" + "name='" + name + "'}";
}
}
public class DelayQueueExample {
public static void main(String[] args) throws InterruptedException {
DelayQueue<DelayedTask> queue = new DelayQueue<>();
// 添加延迟任务
queue.put(new DelayedTask("任务1", 3000)); // 3秒后执行
queue.put(new DelayedTask("任务2", 1000)); // 1秒后执行
queue.put(new DelayedTask("任务3", 2000)); // 2秒后执行
System.out.println("开始处理延迟任务...");
while (!queue.isEmpty()) {
DelayedTask task = queue.take();
System.out.println("执行: " + task + " at " + System.currentTimeMillis());
}
}
}
6. 同步队列(SynchronousQueue)
import java.util.concurrent.SynchronousQueue;
public class SynchronousQueueExample {
public static void main(String[] args) {
SynchronousQueue<String> queue = new SynchronousQueue<>();
// 生产者
new Thread(() -> {
try {
String data = "重要数据";
System.out.println("生产者: 准备发送 " + data);
queue.put(data);
System.out.println("生产者: 数据已发送");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
// 消费者
new Thread(() -> {
try {
Thread.sleep(1000); // 模拟处理时间
String data = queue.take();
System.out.println("消费者: 接收到 " + data);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
}
}
7. 队列方法对比
| 方法 | 抛出异常 | 返回特殊值 |
|---|---|---|
| 插入 | add(e) | offer(e) |
| 移除 | remove() | poll() |
| 检查 | element() | peek() |
阻塞队列特有方法:
put(e)- 阻塞直到空间可用take()- 阻塞直到元素可用offer(e, timeout, unit)- 带超时的插入poll(timeout, unit)- 带超时的移除
8. 选择指南
- 常规队列:LinkedList, ArrayDeque
- 优先级处理:PriorityQueue
- 生产消费模式:ArrayBlockingQueue, LinkedBlockingQueue
- 高并发:ConcurrentLinkedQueue
- 延迟任务:DelayQueue
- 直接传递:SynchronousQueue
选择队列类型时需要考虑线程安全、性能需求、是否阻塞等因素。
更多推荐



所有评论(0)