JUC高并发编程9:阻塞队列

9 篇文章 0 订阅

1 概述和架构

在并发编程中,队列和栈是两种常见的数据结构,它们在不同的场景下有不同的应用。阻塞队列是一种特殊的队列,它在多线程环境中提供了线程安全的操作,并且在队列为空或满时能够阻塞线程,从而避免资源竞争和数据不一致的问题。

1.1 队列和栈

1.1.1 队列(Queue)

队列是一种先进先出(FIFO, First In First Out)的数据结构。元素从队列的一端(称为队尾)插入,从另一端(称为队头)移除。队列常用于任务调度、消息传递等场景。

  • 先进先出:最先进入队列的元素最先被移除。
  • 应用场景:任务调度、消息队列、缓冲区等。

1.1.2 栈(Stack)

栈是一种后进先出(LIFO, Last In First Out)的数据结构。元素从栈的同一端(称为栈顶)插入和移除。栈常用于函数调用、表达式求值等场景。

  • 后进先出:最后进入栈的元素最先被移除。
  • 应用场景:函数调用栈、表达式求值、撤销操作等。

1.2 阻塞队列(Blocking Queue)

阻塞队列是一种特殊的队列,它在多线程环境中提供了线程安全的操作,并且在队列为空或满时能够阻塞线程。阻塞队列常用于生产者-消费者模型中,生产者线程向队列中添加元素,消费者线程从队列中移除元素。

1.2.1 阻塞队列的特点

  • 阻塞操作

    • 当队列是空的,从队列中获取元素的操作将会被阻塞,直到其他线程往队列中插入新的元素。
    • 当队列是满的,从队列中添加元素的操作将会被阻塞,直到其他线程从队列中移除一个或多个元素或者完全清空,使队列变得空闲起来并后续新增。
  • 线程安全:阻塞队列提供了线程安全的操作,多个线程可以同时对队列进行操作而不会导致数据不一致。

1.3 阻塞队列的架构

阻塞队列的架构通常包括以下几个核心组件:

  1. 队列容器:用于存储元素的数据结构,可以是数组、链表等。
  2. 锁机制:用于保证线程安全的同步机制,通常使用 ReentrantLock 或其他同步工具。
  3. 条件变量:用于线程间的通信,当队列为空或满时,线程会被阻塞,直到满足条件。

2 阻塞队列的分类和核心方法

阻塞队列是并发编程中常用的数据结构,它提供了线程安全的操作,并且在队列为空或满时能够阻塞线程。Java 提供了多种阻塞队列的实现,每种实现都有其特定的应用场景。

2.1 阻塞队列分类

Java 提供了以下几种常见的阻塞队列实现:

  1. ArrayBlockingQueue:基于数组的有界阻塞队列,容量固定,支持公平和非公平锁。
  2. LinkedBlockingQueue:基于链表的可选有界阻塞队列,容量可以指定或不指定(默认是 Integer.MAX_VALUE)。
  3. DelayQueue:无界阻塞队列,元素只有在延迟期满时才能被取出。
  4. PriorityBlockingQueue:无界阻塞队列,元素按照优先级顺序取出。
  5. SynchronousQueue:不存储元素的阻塞队列,每个插入操作必须等待一个移除操作,反之亦然。
  6. LinkedTransferQueue:基于链表的无界阻塞队列,支持高效的插入和移除操作。

2.2 核心方法

阻塞队列提供了多种操作方法,根据不同的需求,可以选择不同的方法。以下是阻塞队列的核心方法分类:
在这里插入图片描述

2.2.1 抛出异常

当操作无法立即执行时,抛出异常。

  • 插入add(e)
    • 如果队列已满,抛出 IllegalStateException
  • 移除remove()
    • 如果队列为空,抛出 NoSuchElementException
  • 检查element()
    • 返回队列头部的元素,如果队列为空,抛出 NoSuchElementException

2.2.2 特殊值

当操作无法立即执行时,返回特殊值(如 nullfalse)。

  • 插入offer(e)
    • 如果队列已满,返回 false
  • 移除poll()
    • 如果队列为空,返回 null
  • 检查peek()
    • 返回队列头部的元素,如果队列为空,返回 null

2.2.3 阻塞

当操作无法立即执行时,阻塞线程,直到操作可以执行。

  • 插入put(e)
    • 如果队列已满,阻塞线程,直到队列有空闲空间。
  • 移除take()
    • 如果队列为空,阻塞线程,直到队列有元素。
  • 检查:不可用
    • 阻塞队列不提供阻塞的检查方法。

2.2.4 超时

当操作无法立即执行时,阻塞线程,直到操作可以执行或超时。

  • 插入offer(e, time, unit)
    • 如果队列已满,阻塞线程,直到队列有空闲空间或超时。
  • 移除poll(time, unit)
    • 如果队列为空,阻塞线程,直到队列有元素或超时。
  • 检查:不可用
    • 阻塞队列不提供超时的检查方法。

3 核心方法演示

public class BlockingQueueDemo {
    public static void main(String[] args) throws InterruptedException {
        // 创建阻塞队列
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);

        // 第一组
/*        System.out.println(blockingQueue.add("a"));
        System.out.println(blockingQueue.add("b"));
        System.out.println(blockingQueue.add("c"));
        System.out.println(blockingQueue.element());

        // System.out.println(blockingQueue.add("w"));
        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());
        System.out.println(blockingQueue.remove());*/

        // 第二组
/*        System.out.println(blockingQueue.offer("a"));
        System.out.println(blockingQueue.offer("b"));
        System.out.println(blockingQueue.offer("c"));
        System.out.println(blockingQueue.offer("www"));

        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());*/

        // 第三组
/*        blockingQueue.put("a");
        blockingQueue.put("b");
        blockingQueue.put("c");
        // blockingQueue.put("w");

        System.out.println(blockingQueue.take());
        System.out.println(blockingQueue.take());
        System.out.println(blockingQueue.take());
        System.out.println(blockingQueue.take());*/

        // 第四组
        System.out.println(blockingQueue.offer("a"));
        System.out.println(blockingQueue.offer("b"));
        System.out.println(blockingQueue.offer("c"));
        System.out.println(blockingQueue.offer("w",3L, TimeUnit.SECONDS));

        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll(3L,TimeUnit.SECONDS));


    }
}

4 思维导图

在这里插入图片描述

5 参考链接

【尚硅谷】大厂必备技术之JUC并发编程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值