LinkedBlockingQueue讲解

LinkedBlockingQueue

LinkedBlockingQueue 是 Java 中 java.util.concurrent 包的一部分,属于并发集合类。它是一个基于链表实现的阻塞队列,适用于生产者-消费者模型。

主要特性
  1. 阻塞行为:
    • LinkedBlockingQueue 提供了阻塞的 puttake 方法,当队列满时,put 方法会阻塞直到有空间;当队列为空时,take 方法会阻塞直到有元素可取。
  2. 线程安全:
    • 它使用了锁机制来保证线程安全,确保多个线程能够正确地访问和修改队列。
  3. 有界/无界队列:
    • LinkedBlockingQueue 可以被设置为有界(指定最大容量)或无界(默认容量为 Integer.MAX_VALUE)。
  4. 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 非常适合用于生产者-消费者模型,多个生产者线程可以安全地将数据放入队列,而多个消费者线程可以安全地从队列中取数据。
  • 任务队列: 用于线程池中的任务队列,线程池中的工作线程从队列中取任务执行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值