JAVABlockingQueue的原理和使用

程序你得看得懂 2024-02-24 03:02:11

BlockingQueue 是 Java 并发编程中常用的数据结构,它支持两个附加的操作:在尝试检索元素但队列为空时阻塞,以及在尝试添加元素但队列已满时阻塞。BlockingQueue 不接受 null 元素。

原理

BlockingQueue 是一种线程安全的队列,常用于生产者-消费者模式。它内部通过锁、条件变量等机制实现线程间的同步。当队列为空时,从队列中获取元素的线程将会被阻塞,直到队列中有新的元素可供消费;当队列已满时,尝试向队列中添加元素的线程也会被阻塞,直到队列中有空闲的位置可供新元素。

使用

BlockingQueue 提供了多种方法来支持阻塞的插入和移除操作,如 put(E e), take(), offer(E e, long timeout, TimeUnit unit), poll(long timeout, TimeUnit unit) 等。

put(E e): 将指定的元素插入到此队列的末尾(如果立即可行且不会违反容量限制),在成功时返回,如果当前没有可用的空间,则它将等待(即阻塞)。take(): 检索并移除此队列的头部,在元素变得可用之前一直等待(即阻塞)。offer(E e, long timeout, TimeUnit unit): 将指定的元素插入到此队列中(如果立即可行且不会违反容量限制),成功时返回 true,如果当前没有可用的空间,则它将等待指定的等待时间。poll(long timeout, TimeUnit unit): 检索并移除此队列的头部,在元素变得可用之前一直等待指定的等待时间。示例代码

下面是一个简单的生产者-消费者示例,使用 BlockingQueue:

import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; Producer implements Runnable { private final BlockingQueue<Integer> queue; public Producer(BlockingQueue<Integer> queue) { this.queue = queue; } @Override public void run() { try { for (int i = 0; i < 10; i++) { System.out.println("Produced: " + i); queue.put(i); Thread.sleep(200); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } Consumer implements Runnable { private final BlockingQueue<Integer> queue; public Consumer(BlockingQueue<Integer> queue) { this.queue = queue; } @Override public void run() { try { while (true) { Integer i = queue.take(); System.out.println("Consumed: " + i); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } public Main { public static void main(String[] args) { BlockingQueue<Integer> queue = new LinkedBlockingQueue<>(1024); Producer producer = new Producer(queue); Consumer consumer = new Consumer(queue); new Thread(producer).start(); new Thread(consumer).start(); } }

在这个示例中,Producer 类生产整数并将其放入 BlockingQueue,而 Consumer 类从队列中取出并消费这些整数。通过使用 BlockingQueue,我们能够实现生产者和消费者之间的同步,而无需编写复杂的同步代码。

0 阅读:10

程序你得看得懂

简介:感谢大家的关注