Java 阻塞队列

BlockingQueue 接口定义了阻塞队列的操作。在本教程中,我们将了解 Java BlockingQueue 接口及其方法。

在本教程中,我们将了解 Java BlockingQueue 接口及其方法。

在 Java 集合框架中,BlockingQueue 接口扩展了 Queue 接口,它定义了阻塞队列的操作。它的操作都是可等待的,直到满足执行的条件。

例如,如果我们想从一个空队列中删除一个元素,那么阻塞队列允许删除操作等待,直到队列中有了可供删除的元素。

BlockingQueue 的实现类

BlockingQueue 是一个接口,只是定义了阻塞队列的行为,而没有实现这些行为。Java 集合框架中提供了 2 个组赛队列的实现类:

ArrayBlockingQueue 和 LinkedBlockingQueue 在 Java 中实现了 BlockingQueue 接口。

我们根据自己的需要选择使用 ArraryBlockingQueueLinkedBlockingQueue 创建阻塞队列。

BlockingQueue<String> animal1 = new ArraryBlockingQueue<>();
BlockingQueue<String> animal2 = new LinkedBlockingQueue<>();

阻塞队列的方法

根据队列是满还是空,阻塞队列的方法可以分为 3 类:

抛出异常的方法

  • add() - 在队列末尾插入一个元素到阻塞队列。如果队列已满则抛出异常。
  • element() - 返回阻塞队列的头部。如果队列为空,则抛出异常。
  • remove() - 从阻塞队列中移除一个元素。如果队列为空,则抛出异常。

返回一些值的方法

  • offer() - 将指定元素插入队列末尾的阻塞队列。如果队列已满则返回 false
  • peek() - 返回阻塞队列的头部。如果队列为空则返回 null
  • poll() - 从阻塞队列中移除一个元素。如果队列为空则返回 null

关于 offer() 和 poll()

offer()poll() 方法都可用设置超时时间。也就是说,我们可以将超时时间参数传递。例如,

offer(value, 100, milliseconds)

这里,

  • value 是要插入队列的元素
  • 100 是超时时间,时间单位由第三个参数指定
  • milliseconds 超时时间的时间单位是毫秒。 时间单位可参考枚举类 java.util.concurrent.TimeUnit

这意味着 offer() 方法将尝试在 100 毫秒内向阻塞队列插入一个元素。如果在 100 毫秒内无法插入元素,则返回 false

阻塞操作的方法

BlockingQueue 还提供了一些方法进行阻塞操作。阻塞方法在没有满足条件的时候会一直等待,直到满足跳进。

  • put() - 向阻塞队列插入一个元素。如果队列已满,它将等待队列有空间插入元素。
  • take() - 从阻塞队列中移除并返回一个元素。如果队列为空,它会一直等到队列中有要删除的元素。

ArrayBlockingQueue 中 BlockingQueue 的实现

ArrayBlockingQueue 类实现了 BlockingQueue 接口,我们可以是用 ArrayBlockingQueue 类创建阻塞队列。

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ArrayBlockingQueue;

public class Main {

  public static void main(String[] args) {
    // Create a blocking queue using the ArrayBlockingQueue
    BlockingQueue<Integer> numbers = new ArrayBlockingQueue<>(5);

    try {
      // 插入元素到阻塞队列
      numbers.put(2);
      numbers.put(1);
      numbers.put(3);
      System.out.println("BLockingQueue: " + numbers);

      // 从阻塞队列删除元素
      int removedNumber = numbers.take();
      System.out.println("Removed Number: " + removedNumber);
    } catch (Exception e) {
      e.getStackTrace();
    }
  }
}

输出

BLockingQueue: [2, 1, 3]
Removed Number: 2

要了解 ArrayBlockingQueue 更多信息,请访问 Java ArrayBlockingQueue 类

何时使用阻塞队列?

在 Java 中, BlockingQueue 被认为是线程安全的集合,在多线程环境中对你会有所帮助。

阻塞队列一个常用的场景是在生产者消费者模式中。

我们实现生产者消费者模式的时候,可以使用阻塞队列作为中间的产品仓库,生产者线程生产了产品之后会将产品放入仓库,消费者线程在需要的时候从仓库拿走产品。

如果生产的快而消费的慢,那么仓库(队列)满了之后,生产者线程就要等待仓库有空间才能放入新的产品。

如果生产的慢而消费的快,那么仓库(队列)空了之后,消费者线程就要等待仓库中有了产品之后才能拿走。