BlockingDeque 是 Java 并发包中线程安全的双端阻塞队列接口,支持 FIFO/LIFO 操作及空/满时阻塞;常用实现为 LinkedBlockingDeque,具备 add/offer/put/take/poll 四类语义方法,适用于生产者-消费者双向协作场景。

BlockingDeque 是 Java 并发包(java.util.concurrent)中提供的线程安全双端阻塞队列接口,它既支持 FIFO 也支持 LIFO 操作,并在队列空或满时提供阻塞能力。实际开发中,常用实现类是 LinkedBlockingDeque(基于链表、可选容量限制)和 ArrayBlockingDeque(注意:JDK 并未提供 ArrayBlockingDeque,这是常见误解;实际只有 ArrayBlockingQueue,而双端队列的数组实现需自行封装或使用其他库)。因此,以下以 LinkedBlockingDeque 为主展开说明。
理解 BlockingDeque 的核心行为
BlockingDeque 继承自 BlockingQueue 和 Deque,具备四类操作方式(每类含“抛异常”“返回特殊值”“阻塞”“超时等待”四种语义),但最常用的是带阻塞语义的方法:
- addFirst(e) / addLast(e):队列满时抛 IllegalStateException
- offerFirst(e) / offerLast(e):队列满时返回 false,不阻塞
- putFirst(e) / putLast(e):队列满时阻塞,直到有空间
- takeFirst() / takeLast():队列空时阻塞,直到有元素
- pollFirst(timeout, unit) / pollLast(timeout, unit):支持超时等待,超时返回 null
典型使用场景:生产者-消费者双向协作
比如一个日志处理系统,前端接收日志(从尾部写入),后台按优先级调度(从头部取高优日志,从尾部取普通日志)。此时可用 BlockingDeque 实现灵活调度:
示例代码片段:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
BlockingDeque<String> logQueue = new LinkedBlockingDeque<>(1000);
// 生产者:统一从尾部添加
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
logQueue.putLast("NORMAL-" + i);
if (i % 3 == 0) {
logQueue.putFirst("URGENT-" + i); // 插入头部,优先处理
}
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}).start();
// 消费者:优先从头部取紧急日志,再从尾部取普通日志
new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
try {
String log = logQueue.pollFirst(500, TimeUnit.MILLISECONDS);
if (log != null) {
System.out.println("处理紧急日志:" + log);
} else {
log = logQueue.pollLast(500, TimeUnit.MILLISECONDS);
if (log != null) {
System.out.println("处理普通日志:" + log);
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}).start();
注意容量与线程安全性细节
LinkedBlockingDeque 默认无界(capacity=Integer.MAX_VALUE),但建议显式指定容量,避免内存耗尽:
- 构造时传入正整数容量(如
new LinkedBlockingDeque<>(2048)),使其变为有界队列,此时 putFirst/putLast 会阻塞 - 无界队列下,put 系列方法永远不会阻塞(等价于 offer),仅 take/poll 阻塞或等待
- 所有操作天然线程安全,无需额外同步;但批量操作(如 removeAll)不保证原子性,慎用于并发修改场景
- 迭代器弱一致性:遍历时可能反映部分更新,不抛 ConcurrentModificationException,但不保证实时精确
对比其他双端队列的选择建议
不要混淆以下类型:
- Deque(非并发):如 ArrayDeque、LinkedList,非线程安全,多线程需手动加锁
- BlockingQueue(单端):如 ArrayBlockingQueue、LinkedBlockingQueue,只支持一端入、一端出
- BlockingDeque:唯一支持两端阻塞插入/移除的标准并发双端队列
- 若需更高性能或更丰富功能(如内存池、延迟双端操作),可考虑第三方库如 JCTools 的
MpscUnboundedXaddArrayQueue(但非标准双端)


















