【Java-多线程】什么是阻塞队列?阻塞队列有哪些常用的应用场景?

让我们通过一个外卖平台案例来理解阻塞队列。假设某外卖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();

一、阻塞队列核心特性

  1. 阻塞机制

    • 队列满时,put操作自动阻塞
    • 队列空时,take操作自动阻塞
    • 支持超时等待(offer(e, timeout, unit) / poll(timeout, unit))
  2. 线程安全
    内置ReentrantLock保证原子操作

  3. 通知机制
    使用Condition实现生产者-消费者的等待/唤醒


二、7种阻塞队列类型对比

队列类型数据结构边界排序规则特色功能
ArrayBlockingQueue数组有界FIFO固定容量,共用锁
LinkedBlockingQueue链表可选界FIFO双锁分离,高吞吐
PriorityBlockingQueue无界优先级排序自定义Comparator
DelayQueue优先级堆无界到期时间排序元素需实现Delayed接口
SynchronousQueue零容量直接传递生产消费必须成对出现
LinkedTransferQueue链表无界FIFO支持tryTransfer即时传递
LinkedBlockingDeque双向链表可选界FIFO/LIFO支持首尾双端操作

三、生产级应用场景

  1. 分布式日志收集系统

    // 使用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();
        }
    }
    
  2. 电商秒杀系统

    阻塞队列处理
    ArrayBlockingQueue
    秒杀队列.put
    订单处理Worker1
    订单处理Worker2
    订单处理Worker3
    用户请求
    库存是否>0?
    生成订单
    创建支付订单
    返回已售罄
  3. 实时股票报价系统

    // 使用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为例)

ProducerBlockingQueueConsumer队列已满put(element)等待(Condition.await())消费者取出元素take()返回元素Condition.signal()生产者恢复插入元素ProducerBlockingQueueConsumer

五、最佳实践总结

  1. 容量规划

    • IO密集型场景:设置较大容量(如1000+)
    • 内存敏感场景:使用有界队列防止OOM
  2. 吞吐量优化

    • 读多写少用LinkedBlockingQueue
    • 写多读少用ArrayBlockingQueue
  3. 异常处理

    try {
        queue.put(data);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        logger.error("Producer interrupted", e);
    }
    
  4. 监控指标

    // 监控队列饱和度
    double saturation = (double)queue.size() / queue.remainingCapacity();
    if (saturation > 0.8) {
        alert("队列即将满载!");
    }
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值