跳到主要内容

如何在 Java 中实现一个阻塞队列?

参考答案:

在Java中,你可以使用java.util.concurrent包中的BlockingQueue接口来实现一个阻塞队列。这个接口已经定义了阻塞队列的主要行为,包括在队列为空时阻塞取队列元素的线程,以及当队列已满时阻塞添加元素的线程。

以下是一个简单的示例,使用ArrayBlockingQueue实现阻塞队列:

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

public class BlockingQueueExample {

    public static void main(String[] args) throws InterruptedException {
        BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(5); // 创建一个容量为5的阻塞队列

        // 启动一个生产者线程
        Thread producer = new Thread(() -> {
            try {
                for (int i = 0; i < 10; i++) {
                    System.out.println("生产者生产了: " + i);
                    queue.put(i); // 如果队列满,则阻塞
                    Thread.sleep(1000); // 暂停一秒,模拟生产过程
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        // 启动一个消费者线程
        Thread consumer = new Thread(() -> {
            try {
                while (true) {
                    Integer num = queue.take(); // 如果队列空,则阻塞
                    System.out.println("消费者消费了: " + num);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        producer.start();
        consumer.start();

        // 等待生产者线程结束
        producer.join();

        // 停止消费者线程
        queue.put(new Integer(999)); // 这将唤醒正在等待的消费者线程,并使其结束
    }
}

在这个例子中,我们创建了一个容量为5的ArrayBlockingQueue。我们启动了一个生产者线程,它每秒向队列中添加一个元素。同时,我们启动了一个消费者线程,它不断地从队列中取出元素并打印。当队列满时,生产者线程将被阻塞,直到队列中有空闲位置。当队列空时,消费者线程将被阻塞,直到队列中有新的元素。

需要注意的是,当我们在主线程中调用producer.join()时,主线程会等待生产者线程结束。然后,我们向队列中添加一个特殊的元素(这里我们使用了999),这将唤醒正在等待的消费者线程,并使其结束。

注意,虽然这个例子中的生产者和消费者都是单线程的,但在实际使用中,你可能会希望有多个生产者和消费者线程,以充分利用多核处理器的性能。

此外,Java还提供了其他几种类型的阻塞队列,如LinkedBlockingQueuePriorityBlockingQueueDelayQueue等,你可以根据实际需要选择合适的类型。