JUC之阻塞队列

什么是阻塞队列

阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。这两个附加的操作是: 在队列为空时, 获取元素的线程会等待队列变为非空。当队列满时, 存储元素的线程会等待队列可用。阻塞队列常用于生产者和消费者的场景, 生产者是往队列里添加元素的线程, 消费者是从队列里拿元素的线程。阻塞队列就是生产者存放元素的容器, 而消费者也只从容器里拿元素。

  • 当队列是空的, 从队列中获取元素的操作将会被阻塞
  • 当队列是满的, 从队列中添加元素的操作将会被阻塞
  • 试图从空的队列中获取元素的线程将会被阻塞, 直到其他线程往空的队列插入新的元素
  • 试图向已满的队列中添加新元素的线程将会被阻塞, 直到其他线程从队列中移除一个或多个元素或者完全清空, 使队列变得空闲起来并后续新增

阻塞队列种类

  1. ArrayBlockingQueue

    • 基于数组构成的有界阻塞队列
    • 在生产者插入数据和消费者获取数据时用的是同一把锁, 无法并行
  2. LinkedBlockingQueue

    • 基于链表构成的有界(默认值为Integer.MAX_VALUE)阻塞队列
    • 插入数据和获取数据分别采用了独立的锁, 有较好的并发性能
  3. DelayQueue

    • 基于优先级队列实现的延迟无界阻塞队列
    • DelayQueue 中的元素只有当其指定的延迟时间到了, 才能够从队列中获取到该元素。
    • DelayQueue 是一个没有大小限制的队列, 因此往队列中插入数据的操作永远不会被阻塞, 只有获取数据的操作才会被阻塞
  4. PriorityBlockingQueue

    • 基于优先级队列实现的无界阻塞队列
    • 支持优先级排序
    • 不会阻塞生产者, 当队列中没有数据时, 会阻塞消费者
  5. SynchronousQueue

    • 一种无缓冲的等待队列
    • 相对于有缓冲的BlockingQueue来说, 少了一个中间环节(缓冲区)
    • 不存储元素, 是一个单个元素的队列

    SynchronousQueue公平模式与非公平模式的区别

    • 公平模式: SynchronousQueue 会采用公平锁, 并配合一个 FIFO 队列来阻塞多余的生产者和消费者, 从而体系整体的公平策略
    • 非公平模式(默认):SynchronousQueue 采用非公平锁, 同时配合一个 LIFO 队列来管理多余的生产者和消费者, 再高并发的情况下容易出现线程饥饿
  6. LinkedTransferQueue

    • 基于链表结构实现的无界TransferQueue队列
    • 预占模式: 意思就是消费者线程取元素时, 如果队列不为空, 则直接取走数据, 若队列为空, 生成一个节点(元素为 null)入队, 消费者线程被等待在这个节点上, 生产者线程入队时发现有一个元素为 null 的节点, 生产者线程就不入队了, 直接就将元素填充到该节点, 并唤醒该节点等待的线程, 被唤醒的消费者线程取走元素, 从调用的方法返回
  7. LinkedBlockingDeque

    • 基于链表实现的双向有界阻塞队列
    • 可以从队列的两端插入和移除元素, 双向队列因为多了一个操作队列的入口, 在多线程同时入队时, 也就减少了一半的竞争
    • 插入元素时: 如果当前队列已满将会进入阻塞状态, 一直等到队列有空的位置时再该元素插入, 该操作可以通过设置超时参数, 超时后返回 false 表示操作失败, 也可以不设置超时参数一直阻塞, 中断后抛出 InterruptedException异常
    • 读取元素时: 如果当前队列为空会阻塞住直到队列不为空然后返回元素, 同样可以通过设置超时参数

核心方法

方法类型抛出异常特殊值阻塞超时
插入add(e)offer(e)put(e)offer(e, time, unit)
移除remove()poll()take()poll(time, unit)
检查element()peek()NANA

各种方法类型的具体效果

方法类型效果
抛出异常当阻塞队列满时, 再往队列里add插入元素会抛出IllegalStateException:Queue full
当阻塞队列空时, 再对队列remove移除元素会抛出NoSuchElementException
特殊值插入方法, 成功返回true, 失败返回false
移出方法, 成功返回取出的元素, 失败返回null
阻塞当阻塞队列满时, 生产者线程继续往队列里put元素, 队列就会一直阻塞生产者知道put数据成功或中断退出
当阻塞队列空时, 消费者线程试图从队列里take元素, 队列就会一直阻塞消费者线程知道队列里有数据
超时当阻塞队列满时, 队列会阻塞生产者线程, 超过等待时限后生产者线程会退出
当阻塞队列空时, 队列会阻塞消费者线程, 超过等待时限后消费者线程会退出

我的个人主页: www.ayu.link
本文连接: ┏ (゜ω゜)=☞

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值