阻塞队列BlockingQueue

一、BlockingQueue 是什么?

自带阻塞功能的线程安全队列

  • 队空:取数据的线程会阻塞等待
  • 队满:放数据的线程会阻塞等待
  • 天然实现生产者 - 消费者模型完全不用写 wait/notify

核心方法(必须记住):

  • put(e):队满则阻塞
  • take():队空则阻塞
  • offer(e) / poll():不阻塞,返回布尔 /null

二、四大常用阻塞队列(本质区别)

1. ArrayBlockingQueue(有界数组队列)

  • 底层:数组
  • 边界必须指定容量,有界
  • 一把锁(入队、出队共用同一把 ReentrantLock)
  • 特点:简单、公平 / 非公平可选、内存连续
  • 场景:需要严格限制队列大小,防止无限排队
1
BlockingQueue<String> queue = new ArrayBlockingQueue<>(10);

2. LinkedBlockingQueue(无界 / 有界链表队列)

  • 底层:单向链表

  • 边界:可指定容量;不指定就是 Integer.MAX_VALUE(近似无界)

  • 两把锁

    • takeLock(取数据)

    • putLock(放数据)

      入队出队可并发,性能更高

  • 场景线程池默认使用,吞吐量高

1
BlockingQueue<String> queue = new LinkedBlockingQueue<>(); // 无界

3. SynchronousQueue(不存储元素的队列)

  • 容量 = 0

  • 不存数据,生产者必须等消费者,消费者必须等生产者

  • 相当于直接交换数据,不经过缓冲区

  • :默认无锁(CAS 实现)

  • 场景

    任务不排队,直接交给线程执行

    CachedThreadPool 用的就是它

1
BlockingQueue<String> queue = new SynchronousQueue<>();

4. PriorityBlockingQueue(优先级队列)

  • 底层:数组(最小堆实现)
  • 边界:无界(自动扩容)
  • 特点:元素按优先级出队,不是 FIFO
  • 场景:需要按优先级处理任务

三、阻塞队列的线程安全是怎么实现的?

全部基于:ReentrantLock + Condition

底层模板几乎一样:

1
2
3
final ReentrantLock lock;
private final Condition notEmpty; // 取数据等待
private final Condition notFull; // 放数据等待

take () 阻塞流程:

  1. 加锁
  2. 如果队空 → notEmpty.await() 阻塞等待
  3. 被唤醒 → 取数据
  4. 唤醒正在等待 put 的线程 notFull.signal()
  5. 解锁

put () 阻塞流程:

  1. 加锁
  2. 如果队满 → notFull.await() 阻塞等待
  3. 被唤醒 → 放数据
  4. 唤醒正在等待 take 的线程 notEmpty.signal()
  5. 解锁

一句话:锁保证线程安全,Condition 实现精准阻塞唤醒。


四、阻塞队列与线程池如何配合?

线程池运行流程 = 阻塞队列的真实使用场景

  1. 任务进来 → 核心线程数未满?

    → 创建核心线程执行

  2. 核心线程满了 →

    任务进入阻塞队列排队

  3. 队列满了 →

    → 创建非核心线程

  4. 最大线程也满了 →

    → 拒绝策略


线程池与队列对应关系

1. FixedThreadPool(固定线程数)

1
new LinkedBlockingQueue()
  • 无界队列
  • 任务无限排队
  • 不会创建非核心线程
  • 风险:OOM

2. CachedThreadPool(缓存线程池)

1
new SynchronousQueue()
  • 队列容量 = 0
  • 任务不排队
  • 来一个任务创建一个线程
  • 适合:大量短任务

3. SingleThreadExecutor(单线程)

1
new LinkedBlockingQueue()
  • 所有任务排队,单线程串行执行

五、4 个阻塞队列一句话总结

  1. ArrayBlockingQueue:数组、有界、一把锁、公平可选
  2. LinkedBlockingQueue:链表、有界 / 无界、两把锁、线程池默认
  3. SynchronousQueue:不存数据、直接交换、CachedThreadPool 用
  4. PriorityBlockingQueue:优先级、无界、自动扩容

六、最核心的结论

  • 阻塞队列 = 线程安全 + 自动阻塞 / 唤醒
  • 底层 = ReentrantLock + Condition
  • 线程池的排队、阻塞、复用,全靠阻塞队列实现

总结

  • BlockingQueue:自带阻塞的线程安全队列,用于生产者 - 消费者模式。
  • Array:数组、有界、一锁;Linked:链表、无界、双锁、高性能。
  • SynchronousQueue:不存数据,直接交换,用于 CachedThreadPool。
  • 线程安全:靠 ReentrantLock + Condition 实现。
  • 线程池:依靠阻塞队列实现任务排队。

阻塞队列BlockingQueue
http://hanqichuan.com/2026/04/16/java并发/阻塞队列BlockingQueue/
作者
韩启川
发布于
2026年4月16日
许可协议