arrayblockingqueue的put方法在队列满时阻塞生产者线程,基于reentrantlock和condition实现等待唤醒,全程持锁保证原子性,需处理interruptedexception,与offer()的核心区别在于是否强制等待。

ArrayBlockingQueue 的 put 方法会让生产者线程在队列满时自动阻塞,直到有空间可用。它内部基于可重入锁(ReentrantLock)和条件变量(Condition)实现等待/唤醒机制,无需手动控制线程状态。
底层使用独占锁 + 非公平锁保障线程安全
ArrayBlockingQueue 在构造时创建一个 ReentrantLock,默认采用非公平策略。put 操作全程持锁,确保容量检查、元素插入、唤醒消费者等步骤原子执行。
- 调用 put 前先获取 lock,避免多个生产者并发判断容量出错
- 若队列已满(count == items.length),当前线程进入 notFull 条件队列等待
- 其他线程调用 take 或 poll 后触发 notFull.signal(),唤醒一个等待的生产者
阻塞逻辑完全由 Condition.await() 实现
当队列满时,put 不会轮询或忙等待,而是调用 notFull.await(),让当前线程释放锁并挂起,进入 WAITING 状态。该操作由 JVM 线程调度器管理,不消耗 CPU。
- await() 返回前会重新竞争 lock,获得锁后继续执行插入逻辑
- 被中断时抛出 InterruptedException,需显式捕获处理
- 不会因虚假唤醒(spurious wakeup)出错,因为 await 被包裹在 while 循环中反复校验条件
实际使用时要注意异常和中断响应
put 是一个阻塞且可能被中断的方法,必须处理 InterruptedException。忽略它可能导致线程无法响应关闭信号。
- 不要简单吞掉 InterruptedException,应恢复中断状态 Thread.currentThread().interrupt()
- 在业务循环中调用 put 时,建议配合 shutdown 标志位做退出判断
- 如果希望超时控制,改用 offer(E e, long timeout, TimeUnit unit)
与 offer() 的关键区别在于是否强制等待
offer() 在队列满时立即返回 false;put() 则坚持等到有空位——这是“阻塞队列”语义的核心体现。
- put 适合对数据可靠性要求高、允许延迟写入的场景(如日志缓冲、任务分发)
- offer 配合重试或降级策略更适合低延迟敏感系统
- 两者都保证线程安全,但语义不同,选型取决于业务对阻塞行为的接受程度
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











