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) {
// 当队列为空时,阻