Java 实现阻塞队列

引言

阻塞队列是在多线程编程中常用的数据结构,它提供了线程安全的入队和出队操作,并且在队列为空时可以阻塞等待,直到队列不为空,或者在队列已满时可以阻塞等待,直到队列不满。在 Java 中,可以使用 java.util.concurrent 包中的 BlockingQueue 接口来实现阻塞队列。本文将介绍如何使用 Java 实现阻塞队列,并提供了一个逐步实现的示例代码。

概述

在实现阻塞队列之前,我们先来了解一下整个实现过程的步骤。下表展示了创建一个简单的阻塞队列所需的步骤:

步骤 描述
1 定义一个队列容器
2 定义队列的容量
3 定义入队和出队方法
4 定义阻塞等待的方法

接下来,我们将逐步完成这些步骤,并给出相应的代码和注释。

步骤一:定义一个队列容器

我们首先需要定义一个队列容器,用于存储队列中的元素。在 Java 中,可以使用 LinkedList 或者 ArrayDeque 来实现队列容器。在这里,我们选择使用 LinkedList

代码示例:

import java.util.LinkedList;
import java.util.Queue;

public class BlockingQueue<T> {
    private Queue<T> queue;

    public BlockingQueue() {
        queue = new LinkedList<>();
    }
}

步骤二:定义队列的容量

我们需要定义队列的容量,以限制队列中元素的数量。在这里,我们使用一个私有变量 capacity 来表示队列的容量,并在构造函数中进行初始化。

代码示例:

public class BlockingQueue<T> {
    private Queue<T> queue;
    private int capacity;

    public BlockingQueue(int capacity) {
        queue = new LinkedList<>();
        this.capacity = capacity;
    }
}

步骤三:定义入队和出队方法

接下来,我们需要实现入队和出队的方法。在这里,我们使用 synchronized 关键字来保证这两个方法的原子性操作,并使用 wait()notifyAll() 方法来实现阻塞等待。

代码示例:

public class BlockingQueue<T> {
    private Queue<T> queue;
    private int capacity;

    public BlockingQueue(int capacity) {
        queue = new LinkedList<>();
        this.capacity = capacity;
    }

    public synchronized void enqueue(T item) throws InterruptedException {
        // 当队列已满时,阻塞等待
        while (queue.size() == capacity) {
            wait();
        }
        // 入队操作
        queue.add(item);
        // 唤醒可能在等待出队的线程
        notifyAll();
    }

    public synchronized T dequeue() throws InterruptedException {
        // 当队列为空时,阻塞等待
        while (queue.isEmpty()) {
            wait();
        }
        // 出队操作
        T item = queue.poll();
        // 唤醒可能在等待入队的线程
        notifyAll();
        return item;
    }
}

步骤四:定义阻塞等待的方法

最后,我们需要定义一个阻塞等待的方法,以便在队列为空或队列已满时进行阻塞等待的操作。在这里,我们使用 await()signalAll() 方法来实现阻塞等待。

代码示例:

public class BlockingQueue<T> {
    private Queue<T> queue;
    private int capacity;
    private final Object lock = new Object();

    public BlockingQueue(int capacity) {
        queue = new LinkedList<>();
        this.capacity = capacity;
    }

    public void enqueue(T item) throws InterruptedException {
        synchronized (lock) {
            // 当队列已满时,阻塞等待
            while (queue.size() == capacity) {
                lock.wait();
            }
            // 入队操作
            queue.add(item);
            // 唤醒可能在等待出队的线程
            lock.notifyAll();
        }
    }

    public T dequeue() throws InterruptedException {
        synchronized (lock) {
            // 当队列为空时,阻