让我们通过一个外卖平台案例来理解阻塞队列。假设某外卖APP需要处理10万+商家的订单推送:
// 创建有界阻塞队列(容量1000)
BlockingQueue<Order> queue = new ArrayBlockingQueue<>(1000);
// 商家推送订单(生产者线程)
new Thread(() -> {
while (true) {
Order order = getNewOrder();
queue.put(order); // 队列满时自动阻塞
}
}).start();
// 骑手接单(消费者线程)
new Thread(() -> {
while (true) {
Order order = queue.take(); // 队列空时自动阻塞
dispatchToRider(order);
}
}).start();
一、阻塞队列核心特性
-
阻塞机制
- 队列满时,put操作自动阻塞
- 队列空时,take操作自动阻塞
- 支持超时等待(offer(e, timeout, unit) / poll(timeout, unit))
-
线程安全
内置ReentrantLock保证原子操作 -
通知机制
使用Condition实现生产者-消费者的等待/唤醒
二、7种阻塞队列类型对比
队列类型 | 数据结构 | 边界 | 排序规则 | 特色功能 |
---|---|---|---|---|
ArrayBlockingQueue | 数组 | 有界 | FIFO | 固定容量,共用锁 |
LinkedBlockingQueue | 链表 | 可选界 | FIFO | 双锁分离,高吞吐 |
PriorityBlockingQueue | 堆 | 无界 | 优先级排序 | 自定义Comparator |
DelayQueue | 优先级堆 | 无界 | 到期时间排序 | 元素需实现Delayed接口 |
SynchronousQueue | 无 | 零容量 | 直接传递 | 生产消费必须成对出现 |
LinkedTransferQueue | 链表 | 无界 | FIFO | 支持tryTransfer即时传递 |
LinkedBlockingDeque | 双向链表 | 可选界 | FIFO/LIFO | 支持首尾双端操作 |
三、生产级应用场景
-
分布式日志收集系统
// 使用LinkedBlockingQueue缓冲日志 public class LogCollector { private static final int MAX_LOG = 50000; private final BlockingQueue<LogEntry> buffer = new LinkedBlockingQueue<>(MAX_LOG); // 日志生产者 public void collectLog(LogEntry log) throws InterruptedException { buffer.put(log); } // 日志消费者 public void startUploader() { new Thread(() -> { while (true) { LogEntry log = buffer.take(); uploadToElasticsearch(log); } }).start(); } }
-
电商秒杀系统
-
实时股票报价系统
// 使用PriorityBlockingQueue处理VIP客户优先 public class StockQuoteSystem { private final BlockingQueue<QuoteRequest> queue = new PriorityBlockingQueue<>(Comparator .comparingInt(req -> req.userLevel)); class QuoteHandler implements Runnable { public void run() { while (!Thread.currentThread().isInterrupted()) { QuoteRequest request = queue.take(); processRequest(request); } } } public void startHandlers(int poolSize) { ExecutorService exec = Executors.newFixedThreadPool(poolSize); for (int i = 0; i < poolSize; i++) { exec.execute(new QuoteHandler()); } } }
四、阻塞队列工作原理(以ArrayBlockingQueue为例)
五、最佳实践总结
-
容量规划
- IO密集型场景:设置较大容量(如1000+)
- 内存敏感场景:使用有界队列防止OOM
-
吞吐量优化
- 读多写少用LinkedBlockingQueue
- 写多读少用ArrayBlockingQueue
-
异常处理
try { queue.put(data); } catch (InterruptedException e) { Thread.currentThread().interrupt(); logger.error("Producer interrupted", e); }
-
监控指标
// 监控队列饱和度 double saturation = (double)queue.size() / queue.remainingCapacity(); if (saturation > 0.8) { alert("队列即将满载!"); }