博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JUC之阻塞队列
阅读量:2169 次
发布时间:2019-05-01

本文共 2579 字,大约阅读时间需要 8 分钟。

一、什么是阻塞队列

阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。这两个附加的操作支持阻塞的插入和移除方法。

支持阻塞的插入方法:当队列满时,队列会阻塞插入元素的线程,直到队列不满。

支持阻塞的移除方法:当队列为空时,获取元素的线程会等待队列变为非空。

二、为什么需要阻塞队列

好处是我们不需要关心什么时候需要阻塞线程,什么时候唤醒线程,不需要控制wait和notify等。

三、阻塞队列的应用场景

阻塞队列常用于生产者和消费者的场景,生产者是向队列里添加元素的线程,消费者是从队列里取元素的线程。简而言之,阻塞队列是生产者用来存放元素、消费者获取元素的容器。

四、Java 里的阻塞队列

JDK提供了 7 个阻塞队列。分别是

  • ArrayBlockingQueue :一个由数组结构组成的有界阻塞队列。
  • LinkedBlockingQueue :一个由链表结构组成的有界阻塞队列(大小默认为Integer.MAX_VALUE的阻塞队列)。
  • PriorityBlockingQueue :一个支持优先级排序的无界阻塞队列。
  • DelayQueue:一个使用优先级队列实现的延迟无界阻塞队列。
  • SynchronousQueue:一个不存储元素的阻塞队列,即单个元素的队列。
  • LinkedTransferQueue:一个由链表结构组成的无界阻塞队列。
  • LinkedBlockingDeque:一个由链表结构组成的双向阻塞队列。
     

 

五、Queue 接口分析

我们以自上而下的方式,先分析一波 Queue 接口里都定义了哪些方法

// 如果队列容量允许,立即将元素插入队列,成功后返回 // 🌟如果队列容量已满,则抛出异常 boolean add(E e);  //  如果队列容量允许,立即将元素插入队列,成功后返回 // 🌟如果队列容量已满,则返回 false // 当使用有界队列时,offer 比 add 方法更何时 boolean offer(E e);  // 检索并删除队列的头节点,返回值为删除的队列头节点 // 🌟如果队列为空则抛出异常 E remove();  // 检索并删除队列的头节点,返回值为删除的队列头节点 // 🌟如果队列为空则返回 null E poll();  // 检查但不删除队列头节点 // 🌟如果队列为空则抛出异常 E element();  // 检查但不删除队列头节点 // 🌟如果队列为空则返回 null E peek();

总结一下 Queue 接口的方法,分为三个大类:

新增元素到队列容器中:add、offer

从队列容器中移除元素:remove、poll
查询队列头节点是否为空:element、peek

从接口 API 的程序健壮性考虑,可以分为两大类:

健壮 API:offer、poll、peek

非健壮 API:add、remove、element
 

六、BlockingQueue 接口分析

BlockingQueue 接口继承自 Queue 接口,所以有些语义相同的 API 接口就没有放上来解读

// 将指定元素插入队列,如果队列已满,等待直到有空间可用;通过 throws 异常得知,可在等待时打断 // 相对于 Queue 接口而言,是一个全新的方法 void put(E e) throws InterruptedException;  // 将指定元素插入队列,如果队列已满,在等待指定的时间内等待腾出空间;通过 throws 异常得知,可在等待时打断 // 相当于是 offer(E e) 的扩展方法 boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException;  // 检索并除去此队列的头节点,如有必要,等待直到元素可用;通过 throws 异常得知,可在等待时打断 E take() throws InterruptedException;  // 检索并删除此队列的头,如果有必要使元素可用,则等待指定的等待时间;通过 throws 异常得知,可在等待时打断 // 相当于是 poll() 的扩展方法 E poll(long timeout, TimeUnit unit) throws InterruptedException;  // 返回队列剩余容量,如果为无界队列,返回 Integer.MAX_VALUE int remainingCapacity();  // 如果此队列包含指定的元素,则返回 true public boolean contains(Object o);  // 从此队列中删除所有可用元素,并将它们添加到给定的集合中 int drainTo(Collection
c); // 从此队列中最多移除给定数量的可用元素,并将它们添加到给定的集合中 int drainTo(Collection
c, int maxElements);

七、阻塞队列提供了四种处理方法

方法处理方式    抛出异常    返回特殊值    一直阻塞    超时退出
插入方法    add(e)    offer(e)    put(e)    offer(e,time,unit)
移除方法    remove()    poll()    take()    poll(time,unit)
检查方法    element()    peek()    不可用    不可用
抛出异常:是指当阻塞队列满时候,再往队列里插入元素,会抛出IllegalStateException(“Queue full”)异常。当队列为空时,从队列里获取元素时会抛出NoSuchElementException异常 。

返回特殊值:插入方法会返回是否成功,成功则返回true。移除方法,则是从队列里拿出一个元素,如果没有则返回null

一直阻塞:当阻塞队列满时,如果生产者线程往队列里put元素,队列会一直阻塞生产者线程,直到拿到数据,或者响应中断退出。当队列空时,消费者线程试图从队列里take元素,队列也会阻塞消费者线程,直到队列可用。

超时退出:当阻塞队列满时,队列会阻塞生产者线程一段时间,如果超过一定的时间,生产者线程就会退出。

 

 

 

转载地址:http://ghxzb.baihongyu.com/

你可能感兴趣的文章
用 TensorFlow.js 在浏览器中训练神经网络
查看>>
cs230 深度学习 Lecture 2 编程作业: Logistic Regression with a Neural Network mindset
查看>>
梯度消失问题与如何选择激活函数
查看>>
为什么需要 Mini-batch 梯度下降,及 TensorFlow 应用举例
查看>>
为什么在优化算法中使用指数加权平均
查看>>
什么是 Q-learning
查看>>
用一个小游戏入门深度强化学习
查看>>
如何应用 BERT :Bidirectional Encoder Representations from Transformers
查看>>
5 分钟入门 Google 最强NLP模型:BERT
查看>>
强化学习第1课:像学自行车一样的强化学习
查看>>
强化学习第2课:强化学习,监督式学习,非监督式学习的区别
查看>>
强化学习第3课:有些问题就像个赌局
查看>>
强化学习第4课:这些都可以抽象为一个决策过程
查看>>
强化学习第5课:什么是马尔科夫决策过程
查看>>
强化学习第6课:什么是 Crossentropy 方法
查看>>
强化学习第7课:交叉熵方法的一些局限性
查看>>
强化学习 8: approximate reinforcement learning
查看>>
图解什么是 Transformer
查看>>
代码实例:如何使用 TensorFlow 2.0 Preview
查看>>
6 种用 LSTM 做时间序列预测的模型结构 - Keras 实现
查看>>