blockingqueue 是一个自带等待逻辑的线程安全队列接口,put() 遇满阻塞、take() 遇空阻塞,无需手动处理 wait/notify 或锁判断。

BlockingQueue 是什么?一句话说清本质
它不是普通队列,而是一个「自带等待逻辑」的线程安全队列接口——put() 遇满就停,take() 遇空就等,不用手写 wait/notify 或锁判断。
选哪个实现类?看容量和性能需求
别一上来就用 LinkedBlockingQueue,它默认无界(容量 Integer.MAX_VALUE),容易掩盖内存泄漏或背压失控问题。
-
ArrayBlockingQueue:固定大小、数组实现,内存紧凑,适合明确吞吐上限的场景(比如限流缓冲区) -
LinkedBlockingQueue:链表实现,默认无界,但建议显式传参限制容量,例如new LinkedBlockingQueue(1024) -
SynchronousQueue:不存数据,纯中转,适合“生产即消费”强实时场景(如线程池的直接交接) -
PriorityBlockingQueue:支持优先级,但**不保证 FIFO**,且无界,慎用于核心生产者消费者链路
为什么 put/take 比 offer/poll 更适合标准模型?
因为生产者消费者模型的核心诉求是「阻塞式协作」,而不是「尽力而为」。用 offer() 或 poll() 会迫使你手动轮询+sleep,既浪费 CPU,又破坏响应性。
-
put(e):阻塞直到有空间 → 生产者天然守规矩 -
take():阻塞直到有数据 → 消费者天然不空转 - 反例:
offer(e, 1, TimeUnit.SECONDS)返回false后你得决定重试?丢弃?告警?这些逻辑本不该由队列层承担
常见崩溃点:中断处理不当导致线程“假死”
put() 和 take() 都声明抛出 InterruptedException,但很多人只 catch 了事,没重置中断状态,结果线程后续调用 Thread.interrupted() 总是 false,或被其他库误判为“未中断”,造成不可预测挂起。
- 正确做法:catch 后必须调用
Thread.currentThread().interrupt() - 错误写法:
catch (InterruptedException e) { e.printStackTrace(); }—— 这会让中断信号彻底丢失 - 更隐蔽的坑:在
while (true)循环里没检查Thread.currentThread().isInterrupted(),导致无法优雅退出










