阻塞队列是一种特殊类型的队列,其特点是当队列满时,试图往队列中插入元素的线程会被阻塞;当队列空时,试图从队列中取出元素的线程也会被阻塞。阻塞队列通常用于多线程编程中,特别是在实现生产者-消费者模型时。
阻塞队列的实现原理主要涉及线程同步和条件变量。常见的阻塞队列实现有很多,其中两个常见的是:
-
ArrayBlockingQueue(数组阻塞队列):底层基于数组实现,采用可重入锁(ReentrantLock)来进行线程同步。
-
LinkedBlockingQueue(链表阻塞队列):底层基于链表实现,同样也采用可重入锁来进行线程同步。
阻塞队列的实现原理主要依赖于条件变量(Condition),当队列满或空时,使用条件变量来阻塞相应的线程,直到队列不满或不空时,唤醒相应的线程。
下面是一个简单的使用阻塞队列实现生产者-消费者模型的示例,以Java的 ArrayBlockingQueue
为例:
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
class Producer implements Runnable {
private BlockingQueue<Integer> queue;
public Producer(BlockingQueue<Integer> queue) {
this.queue = queue;
}
@Override
public void run() {
try {
for (int i = 1; i <= 10; i++) {
// 生产者生产数据
System.out.println("Producing: " + i);
queue.put(i); // 阻塞直到队列有空闲位置
Thread.sleep(500); // 模拟生产过程
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Consumer implements Runnable {
private BlockingQueue<Integer> queue;
public Consumer(BlockingQueue<Integer> queue) {
this.queue = queue;
}
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
// 消费者消费数据
Integer value = queue.take(); // 阻塞直到队列有数据
System.out.println("Consuming: " + value);
Thread.sleep(1000); // 模拟消费过程
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Main {
public static void main(String[] args) {
BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(5); // 创建一个大小为5的阻塞队列
// 创建生产者和消费者线程
Thread producerThread = new Thread(new Producer(queue));
Thread consumerThread = new Thread(new Consumer(queue));
// 启动线程
producerThread.start();
consumerThread.start();
}
}
在上述示例中,ArrayBlockingQueue
用作阻塞队列,生产者线程负责向队列中生产数据,消费者线程负责从队列中消费数据。由于队列是阻塞的,当队列满或空时,生产者和消费者线程会被阻塞,直到有空间或数据可用