LinkedBlockingQueue
LinkedBlockingQueue
是 Java 中 java.util.concurrent
包的一部分,属于并发集合类。它是一个基于链表实现的阻塞队列,适用于生产者-消费者模型。
主要特性
- 阻塞行为:
LinkedBlockingQueue
提供了阻塞的put
和take
方法,当队列满时,put
方法会阻塞直到有空间;当队列为空时,take
方法会阻塞直到有元素可取。
- 线程安全:
- 它使用了锁机制来保证线程安全,确保多个线程能够正确地访问和修改队列。
- 有界/无界队列:
LinkedBlockingQueue
可以被设置为有界(指定最大容量)或无界(默认容量为Integer.MAX_VALUE
)。
- FIFO(先进先出):
- 元素按插入顺序出队,确保先进先出顺序。
构造方法
LinkedBlockingQueue()
: 创建一个默认容量为Integer.MAX_VALUE
的无界队列。LinkedBlockingQueue(int capacity)
: 创建一个指定容量的有界队列。
private final LinkedBlockingQueue<ImageReaderReference.ImageReference> mPreviewMasterImageQueue = new LinkedBlockingQueue(5);
主要方法
添加元素
boolean add(E e)
: 插入元素,如果队列已满,抛出IllegalStateException
。boolean offer(E e)
: 尝试插入元素,成功返回true
,失败返回false
。void put(E e)
: 插入元素,如果队列已满,阻塞直到有空间。
移除元素
E take()
: 获取并移除队列头部的元素,如果队列为空,阻塞直到有元素。E poll(long timeout, TimeUnit unit)
: 获取并移除队列头部的元素,如果队列为空,等待指定时间,超时返回null
。E poll()
:获取并移除队列头部的元素,如果队列为空,超时返回null
。
查看元素
E peek()
: 获取但不移除队列头部的元素,如果队列为空,返回null
。E element()
: 获取但不移除队列头部的元素,如果队列为空,抛出NoSuchElementException
。
其他方法
int size()
: 返回队列中元素的数量。int remainingCapacity()
: 返回队列的剩余容量。boolean remove(Object o)
: 从队列中移除指定元素。
示例代码
下面是一个简单的生产者-消费者示例,使用 LinkedBlockingQueue
实现:
import java.util.concurrent.LinkedBlockingQueue;
public class ProducerConsumerExample {
private static final int CAPACITY = 5;
private static final LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<>(CAPACITY);
public static void main(String[] args) {
Thread producer = new Thread(new Producer());
Thread consumer = new Thread(new Consumer());
producer.start();
consumer.start();
}
static class Producer implements Runnable {
@Override
public void run() {
try {
int value = 0;
while (true) {
queue.put(value);
System.out.println("Produced " + value);
value++;
Thread.sleep(100); // 模拟生产过程的延迟
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
static class Consumer implements Runnable {
@Override
public void run() {
try {
while (true) {
int value = queue.take();
System.out.println("Consumed " + value);
Thread.sleep(150); // 模拟消费过程的延迟
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
输出结果
Produced 0
Produced 1
Consumed 0
Produced 2
Produced 3
Consumed 1
Produced 4
Produced 5
Consumed 2
Produced 6
Consumed 3
Produced 7
Produced 8
Consumed 4
Produced 9
...
解释:
由于生产者比消费者快(100 毫秒 vs 150 毫秒),队列会在一段时间内填满,达到 CAPACITY
(5)。此时生产者会阻塞,等待消费者腾出空间。
消费者慢于生产者,所以消费者有时会落后几个整数。
当队列达到其最大容量(5)时,生产者将阻塞,直到消费者取出一个元素。
LinkedBlockingQueue
是线程安全的,因此不需要额外的同步来保护对队列的访问。
程序运行期间的行为
- 一开始,生产者会快速生产几个整数,队列从空变为满。
- 消费者开始消费整数,队列内容逐渐减少。
- 由于消费者比生产者慢,队列会在一段时间内保持接近满的状态。
应用场景
- 生产者-消费者模式:
LinkedBlockingQueue
非常适合用于生产者-消费者模型,多个生产者线程可以安全地将数据放入队列,而多个消费者线程可以安全地从队列中取数据。 - 任务队列: 用于线程池中的任务队列,线程池中的工作线程从队列中取任务执行。