在 Java 并发编程中,阻塞队列是核心组件,常用于实现线程安全的生产者-消费者模式。JDK 提供了七种功能不同的阻塞队列,每种队列结构、特性、适用场景均有所不同。
1. ArrayBlockingQueue
:基于数组的有界阻塞队列
特点说明
- 使用数组作为底层存储结构。
- 容量固定,初始化必须指定大小。
- 线程安全,支持阻塞操作。
- 支持公平性设置(可选先进先出线程调度)。
适用场景
适合任务数量可控、需要限制队列长度的线程池或生产者-消费者场景。
示例代码
import java.util.concurrent.ArrayBlockingQueue;
public class ArrayBlockingQueueExample {
public static void main(String[] args) throws InterruptedException {
ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<>(2);
queue.put("A");
queue.put("B");
System.out.println(queue.take()); // 输出 A
}
}
2. LinkedBlockingQueue
:基于链表的有界阻塞队列
特点说明
- 使用链表结构实现。
- 默认容量为 Integer.MAX_VALUE,实际使用应手动设置。
- 入队和出队分别使用独立锁,提高并发性能。
适用场景
适合高并发生产消费模型,是 ThreadPoolExecutor
默认使用的队列类型。
示例代码
import java.util.concurrent.LinkedBlockingQueue;
public class LinkedBlockingQueueExample {
public static void main(String[] args) throws InterruptedException {
LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<>(3);
queue.put(1);
queue.put(2);
System.out.println(queue.take()); // 输出 1
}
}
3. PriorityBlockingQueue
:支持优先级排序的无界阻塞队列
特点说明
- 无界队列,基于优先级堆实现。
- 元素按优先级顺序出队(非 FIFO)。
- 元素需实现
Comparable
接口或提供比较器。
适用场景
适用于任务调度场景,按任务优先级执行。
示例代码
import java.util.concurrent.PriorityBlockingQueue;
public class PriorityBlockingQueueExample {
public static void main(String[] args) throws InterruptedException {
PriorityBlockingQueue<Integer> queue = new PriorityBlockingQueue<>();
queue.put(5);
queue.put(1);
queue.put(3);
System.out.println(queue.take()); // 输出 1
}
}
4. DelayQueue
:基于优先队列的延迟无界阻塞队列
特点说明
- 元素按延时时间排序,到期后才能被消费。
- 元素需实现
Delayed
接口。 - 基于
PriorityQueue
实现。
适用场景
用于定时任务、延迟缓存、订单过期处理等。
示例代码
import java.util.concurrent.*;
import java.util.concurrent.Delayed;
class DelayedTask implements Delayed {
private final long expireTime;
private final String task;
public DelayedTask(String task, long delay, TimeUnit unit) {
this.task = task;
this.expireTime = System.currentTimeMillis() + unit.toMillis(delay);
}
public long getDelay(TimeUnit unit) {
return unit.convert(expireTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
public int compareTo(Delayed other) {
return Long.compare(this.getDelay(TimeUnit.MILLISECONDS), other.getDelay(TimeUnit.MILLISECONDS));
}
public String toString() {
return task;
}
}
public class DelayQueueExample {
public static void main(String[] args) throws InterruptedException {
DelayQueue<DelayedTask> queue = new DelayQueue<>();
queue.put(new DelayedTask("task1", 2, TimeUnit.SECONDS));
queue.put(new DelayedTask("task2", 1, TimeUnit.SECONDS));
System.out.println(queue.take()); // 输出 task2
System.out.println(queue.take()); // 输出 task1
}
}
5. SynchronousQueue
:不存储元素的阻塞队列
特点说明
- 容量为 0,生产必须等待消费。
- 没有缓存能力,适合直接传递任务。
适用场景
适用于任务交接模式,例如线程直接交换数据。
示例代码
import java.util.concurrent.SynchronousQueue;
public class SynchronousQueueExample {
public static void main(String[] args) {
SynchronousQueue<String> queue = new SynchronousQueue<>();
new Thread(() -> {
try {
queue.put("data");
System.out.println("Put done");
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
try {
String data = queue.take();
System.out.println("Take: " + data);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
6. LinkedTransferQueue
:支持直接传输的无界队列
特点说明
- 支持普通入队,也支持直接传输
transfer()
。 - 提高吞吐量,支持检测是否有消费者等待。
- 使用链表结构实现。
适用场景
适合希望任务能立即传递给消费者的场景。
示例代码
import java.util.concurrent.LinkedTransferQueue;
public class LinkedTransferQueueExample {
public static void main(String[] args) {
LinkedTransferQueue<String> queue = new LinkedTransferQueue<>();
new Thread(() -> {
try {
queue.transfer("hello");
System.out.println("Transfer done");
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
try {
String data = queue.take();
System.out.println("Received: " + data);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
7. LinkedBlockingDeque
:支持双端操作的阻塞队列
特点说明
- 支持从队列头或尾部进行插入和移除。
- 提供
putFirst
、putLast
等方法。 - 使用链表结构,有界阻塞队列。
适用场景
适合需要栈 + 队列混合特性的场景,例如任务重试或优先处理。
示例代码
import java.util.concurrent.LinkedBlockingDeque;
public class LinkedBlockingDequeExample {
public static void main(String[] args) throws InterruptedException {
LinkedBlockingDeque<String> deque = new LinkedBlockingDeque<>(3);
deque.putFirst("head");
deque.putLast("tail");
System.out.println(deque.takeFirst()); // 输出 head
System.out.println(deque.takeLast()); // 输出 tail
}
}
总结
队列类型 | 结构 | 是否有界 | 特殊功能 | 适合场景 |
---|---|---|---|---|
ArrayBlockingQueue | 数组 | 有界 | 支持公平锁 | 有界缓存任务 |
LinkedBlockingQueue | 链表 | 有界 | 分离锁设计,高并发性能 | 默认线程池任务队列 |
PriorityBlockingQueue | 堆 | 无界 | 优先级排序 | 任务调度、优先处理 |
DelayQueue | 堆 | 无界 | 延时处理 | 定时任务、延迟处理 |
SynchronousQueue | 无 | 零容量 | 直接交接 | 线程直接通信 |
LinkedTransferQueue | 链表 | 无界 | 传输机制 | 高吞吐量任务交换 |
LinkedBlockingDeque | 链表 | 有界 | 双端阻塞队列 | 栈与队列结合场景 |
我精心收集了一份10万字的java全面知识总结,包括了java几乎所有的面试基础解读,有兴趣可以获取看看
领取方式
https://pan.quark.cn/s/4e6e3d03407a