好的,下面给你一个 BlockingQueue(阻塞队列)详解,包含概念、原理、常见实现类和使用场景。


1. 什么是 BlockingQueue?

BlockingQueue 是 Java 并发包(java.util.concurrent 提供的一个接口,继承自 Queue
它最大的特点是:

  • 在队列为空时,从队列中获取元素的操作会 阻塞
  • 在队列已满时,向队列中添加元素的操作也会 阻塞

这种机制在 生产者-消费者模式 中非常常见,能够高效解决线程同步问题。


2. BlockingQueue 的核心方法

BlockingQueue 提供了 4 类操作方式:

方法类别抛异常特殊值(返回 null/false)阻塞等待超时等待
插入add(e)offer(e)put(e)offer(e, time, unit)
移除remove()poll()take()poll(time, unit)
检查element()peek()————

📌 关键点:

  • put() → 队列满时阻塞。
  • take() → 队列空时阻塞。

3. 常见实现类

(1)ArrayBlockingQueue

  • 基于 数组 的有界阻塞队列(必须指定容量)。
  • 按 FIFO(先进先出)顺序存取。
  • 适合固定大小队列的场景。

(2)LinkedBlockingQueue

  • 基于 链表 的阻塞队列。
  • 默认容量是 Integer.MAX_VALUE(非常大)。
  • 插入、删除性能较好。

(3)PriorityBlockingQueue

  • 支持优先级排序 的无界阻塞队列。
  • 不保证 FIFO,而是根据元素的 优先级 来出队。

(4)DelayQueue

  • 带有 延迟时间 的无界阻塞队列。
  • 只有 到期元素 才能被取出。
  • 常用于 定时任务、缓存过期处理

(5)SynchronousQueue

  • 不存储任何元素 的阻塞队列。
  • 每个 put 必须等待一个 take,反之亦然。
  • 常用于 任务直接交接

(6)LinkedTransferQueue

  • 基于链表的无界阻塞队列,支持 transfer() 方法:
    • transfer() 会阻塞,直到有消费者取走数据。

4. 使用场景

  • 生产者-消费者模式
    • 多个生产者线程往队列 put 数据,多个消费者线程从队列 take 数据。
  • 线程池
    • Java 的 ThreadPoolExecutor 就是用 BlockingQueue 来存放任务的。
  • 定时任务
    • 使用 DelayQueue 实现任务调度。
  • 限流
    • SynchronousQueue 配合线程池实现高效限流。

5. 示例代码

import java.util.concurrent.*;

public class BlockingQueueDemo {
    public static void main(String[] args) {
        BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(3);

        // 生产者线程
        new Thread(() -> {
            try {
                for (int i = 1; i <= 5; i++) {
                    System.out.println("生产:" + i);
                    queue.put(i);  // 队列满时会阻塞
                    Thread.sleep(500);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }).start();

        // 消费者线程
        new Thread(() -> {
            try {
                while (true) {
                    Integer item = queue.take();  // 队列空时会阻塞
                    System.out.println("消费:" + item);
                    Thread.sleep(1000);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }).start();
    }
}

运行结果(大致):

生产:1
消费:1
生产:2
生产:3
消费:2
生产:4
消费:3
生产:5
消费:4
消费:5