概述

阻塞队列有两个特性:
阻塞:当队列为空时,会阻塞队列弹出操作,直到队列不为空。当队列满了时,会阻塞入队操作,直到队列不满。
队列:FIFO,先进先出。

接口:java.util.concurrent.BlockingQueue。
实现接口:Collection , Iterable , Queue
已知常用实现类:

  • ArrayBlockingQueue :底层为数组的阻塞队列。
  • LinkedBlockingDeque :底层为链表的双端阻塞队列。
  • LinkedBlockingQueue :底层为链表的单端阻塞队列。
  • SynchronousQueue :同步队列
BlockingQueue的四组API

这四组API是添加元素、删除元素、获取队首元素的四组API,每组以是否抛出异常,是否阻塞等待为维度进行切分。

先上总表格:

方式 抛出异常 有返回值且不抛出异常 阻塞等待 超时等待
添加 add () offer() put() offer()
移除 remove() poll() take() poll()
获取队首元素 element() peek() - -
测试会抛出异常的方法
public static void testThrowsExceptionApi(){//创建一个阻塞队列,容量为3BlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue<>(3);blockingQueue.add(1);blockingQueue.add(2);blockingQueue.add(3);//单单开放下面代码,会在一个容量为3的队列中加入第4个元素,抛出队列已满的异常//blockingQueue.add(4);System.out.println(blockingQueue.remove());System.out.println(blockingQueue.remove());System.out.println(blockingQueue.remove());//单单开放下面代码,在空队列中移除元素,抛出异常//System.out.println(blockingQueue.remove());//单单开放下面代码,在空队列中获取队首元素,抛出异常//System.out.println(blockingQueue.element());}

正常情况:

往满队列中添加元素:

往空队列中移除元素:

往空队列获取队首元素:

测试不抛出异常且有返回值的Api
 public static void testNonThrowsExceptionApi(){//创建一个阻塞队列,容量为3BlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue<>(3);//添加元素,成功返回true,否则返回falseSystem.out.println(blockingQueue.offer(1));System.out.println(blockingQueue.offer(2));System.out.println(blockingQueue.offer(3));System.out.println(blockingQueue.offer(4));//移除元素,成功返回元素值,失败返回nullSystem.out.println(blockingQueue.poll());System.out.println(blockingQueue.poll());System.out.println(blockingQueue.poll());System.out.println(blockingQueue.poll());//获取队首元素,成功返回元素值,失败返回nullSystem.out.println(blockingQueue.peek());}

结果:都没有抛出异常。

测试阻塞等待Api
 public static void testBlockWaitApi() throws InterruptedException {//创建一个阻塞队列,容量为3BlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue<>(3);blockingQueue.put(1);blockingQueue.put(2);blockingQueue.put(3);//如果打开下面代码。因为此时队列已满,所以会一直阻塞在这里,直到队列不满为止//blockingQueue.put(4);System.out.println(blockingQueue.take());System.out.println(blockingQueue.take());System.out.println(blockingQueue.take());//如果打开下面代码。因为此时队列为空,所以会一直阻塞在这里,直到队列不为空为止//System.out.println(blockingQueue.take());}

结果:
添加时阻塞:会一直阻塞住线程

移除时阻塞:尝试获取空数组元素时,被阻塞住了。

没有阻塞等待的获取队首Api。

测试阻塞超时等待
public static void testBlockWaitApiWithTimeout(){//创建一个阻塞队列,容量为3BlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue<>(3);try {System.out.println(blockingQueue.offer(1, 3, TimeUnit.SECONDS));} catch (InterruptedException e) {e.printStackTrace();}try {System.out.println(blockingQueue.offer(2, 3, TimeUnit.SECONDS));} catch (InterruptedException e) {e.printStackTrace();}try {System.out.println(blockingQueue.offer(3, 3, TimeUnit.SECONDS));} catch (InterruptedException e) {e.printStackTrace();}try {//如果打开下面代码。因为此时队列已满,所以会一直阻塞在这里,直到队列不满或者三秒超时返回falseSystem.out.println(blockingQueue.offer(4, 3, TimeUnit.SECONDS));} catch (InterruptedException e) {e.printStackTrace();}try {System.out.println(blockingQueue.poll(3,TimeUnit.SECONDS));} catch (InterruptedException e) {e.printStackTrace();}try {System.out.println(blockingQueue.poll(3,TimeUnit.SECONDS));} catch (InterruptedException e) {e.printStackTrace();}try {System.out.println(blockingQueue.poll(3,TimeUnit.SECONDS));} catch (InterruptedException e) {e.printStackTrace();}//如果打开下面代码。因为此时队列为空,所以会一直阻塞在这里,直到队列不为空或者等待超时3秒返回null为止try {System.out.println(blockingQueue.poll(3,TimeUnit.SECONDS));} catch (InterruptedException e) {e.printStackTrace();}}

结果:

超时等待没有对应的获取队首元素API。

同步队列SynchronousQueue

同步队列添加元素后,就会阻塞当前线程,然后等待其他线程移除该元素后,才会唤醒那个线程。可以使用它来做一对一的线程间通信。

public class SynchronousQueueDemo {public static void main(String[] args) {SynchronousQueue<Integer> synchronousQueue = new SynchronousQueue<>();new Thread(()->{try {System.out.println("添加元素1前");synchronousQueue.put(1);System.out.println("添加元素1后");System.out.println("添加了元素2前");synchronousQueue.put(2);System.out.println("添加元素2后");System.out.println("添加元素3前");synchronousQueue.put(3);System.out.println("添加元素3后");}catch (InterruptedException e){}}).start();new Thread(()->{try {TimeUnit.SECONDS.sleep(3);System.out.println("释放了元素" + synchronousQueue.take());TimeUnit.SECONDS.sleep(3);System.out.println("释放了元素" + synchronousQueue.take());TimeUnit.SECONDS.sleep(3);System.out.println("释放了元素" + synchronousQueue.take());} catch (InterruptedException e) {e.printStackTrace();}}).start();}
}


由结果可以看出,队列添加元素之后,就会阻塞住线程,然后等待另一个线程移除该元素,该线程也会被唤醒。所以先打印添加元素前,然后添加元素,之后线程阻塞,所以没有先打印添加元素后,而是先打印释放元素,然后添加线程被唤醒,就打印添加元素后。

JUC阻塞队列BlockingQueue讲解相关推荐

  1. java阻塞队列作用_简单理解阻塞队列(BlockingQueue)中的take/put方法以及Condition存在的作用...

    简单理解阻塞队列(BlockingQueue)中的take/put方法以及Condition存在的作用 Condition:可以理解成一把锁的一个钥匙,它既可以解锁(通知放行),又可以加锁(阻塞) n ...

  2. 【JUC】第五章 JUC 阻塞队列、线程池

    第五章 JUC 阻塞队列.线程池 文章目录 第五章 JUC 阻塞队列.线程池 一.阻塞队列 1.简介 2.BlockingQueue 的方法 3.常见的 BlockingQueue 二.线程池 1.简 ...

  3. Java阻塞队列(BlockingQueue)实现 生产者/消费者 示例

    Java阻塞队列(BlockingQueue)实现 生产者/消费者 示例 本文由 TonySpark 翻译自 Javarevisited.转载请参见文章末尾的要求. Java.util.concurr ...

  4. 并发编程-concurrent指南-阻塞队列BlockingQueue

    阻塞队列BlockingQueue,java.util.concurrent下的BlockingQueue接口表示一个线程放入和提取实例的队列. 适用场景: BlockingQueue通常用于一个线程 ...

  5. 抽象同步器AQS应用之--阻塞队列BlockingQueue,如何保证任务一定被消费?

    文章目录 1.阻塞队列简介 2. BlockingQueue源码分析 3. 生产者消费者模型如何保证信息不会丢失? 1.阻塞队列简介 1.1 什么是阻塞队列? 阻塞队列是一个队列 ①:当队列是空的,从 ...

  6. java 阻塞队列 BQ_阻塞队列 BlockingQueue的使用(二)

    原 阻塞队列 BlockingQueue的使用(二) BlockingQueue 的核心方法:方法类型抛出异常特殊值阻塞超时 插入add(e)offer(e)put(e)offer(e,time,un ...

  7. 阻塞队列BlockingQueue源码

    JAVA阻塞队列 在学习线程池框架ThreadPoolExecutor时发现线程池的实现依赖到了阻塞队列BlockingQueue,在队列为空时take方法会阻塞当前线程,因此这里以ThreadPoo ...

  8. java 并发队列_JAVA并发编程:阻塞队列BlockingQueue之SynchronousQueue

    前面在讲解Executors工厂创建可缓存线程的线程池(newCachedThreadPool)的时候有提到过SynchronousQueue队列,该线程池使用 SynchronousQueue 作为 ...

  9. java多线程-阻塞队列BlockingQueue

    大纲 BlockingQueue接口 ArrayBlockingQueue 一.BlockingQueue接口 public interface BlockingQueue<E> exte ...

最新文章

  1. Heartbeat V2.x双机热备安装
  2. 数学建模 概率论与数理统计
  3. 用树莓派DIY血液检测仪,准确率不输专业设备,成本连十分之一都不到
  4. CentOS查看软件源提供的软件版本命令
  5. android setprogress,progressDialog 为什么设置了setProgress()方法无反应?
  6. kitti数据集_神秘的Waymo一反常态,CVPR现场发布大型自动驾驶数据集
  7. 探秘:TriCore处理器中断机制
  8. 三维图形 纵坐标_《从柯氏四级培训效果评估到三维培训课程需求评估》
  9. python-函数之命名空间作用域
  10. UA OPTI512R 傅立叶光学导论21 菲涅尔衍射与夫琅禾费衍射的例子与图像
  11. 【程序源代码】微信小程序开发视频(2021年最新版本)
  12. 目标检测系列1——Overfeat
  13. 采集淘宝商品的销量、交易量-方维
  14. 首先实现储存程序的电子数字计算机是什么,世界上首先实现存储程序的电子计算机是什么...
  15. 关于Office 365 显示语言的设置(注册开通时的语言选择及注册开通后的语言显示修改)
  16. java线程状态和状态切换
  17. toupper() 函数
  18. 时间应该如何“挤”出来
  19. Android 自定义View实现文本水平方向的跑马灯效果
  20. vue中h5下滑加载更多

热门文章

  1. 大数据学习笔记37:Hive - 复杂数据类型
  2. bzoj3129 [Sdoi2013]方程 容斥+扩展lucas
  3. bzoj2285 [SDOI2011]保密 分数规划spfa+最小割
  4. 2017.10.9 放棋子 思考记录
  5. 2017.9.9 股票交易 思考记录
  6. 六、3D-3D ICP问题线性SVD解法与非线性BA解法
  7. python基础练习题(按条件对指定序列求和,打印99乘法表、求斐波那契数列、百马百担、求水仙花数、求n以内的所有质数(素数)和)、集合的讲解、一些公关方法
  8. redis和php有什么,redis与jedis的区别是什么
  9. confirm修改按钮文字_条码设计软件如何调整条形码与条码文字之间的距离
  10. C++:成绩类Score