目录

一、什么是阻塞队列

二、阻塞队列种类分析

三、非阻塞队列


Java提供的线程安全的Queue可以分为阻塞队列和非阻塞队列,其中阻塞队列的典型例子是BlockingQueue,非阻塞队列的典型例子是ConcurrentLinkedQueue,在实际应用中要根据实际需要选用阻塞队列或者非阻塞队列。

一、什么是阻塞队列

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

当阻塞队列是空时,从队列中获取元素的操作将会被阻塞。

当阻塞队列是满时,往队列里添加元素的操作将会被阻塞。

BlockingQueue提供的常用方法如下:

方法\处理方式 抛出异常 返回特殊值 一直阻塞 超时退出
插入方法 add(e) offer(e) put(e) offer(e,time,unit)
移除方法 remove() poll() take() poll(time,unit)
检查方法 add(e) peek() 不可用 不可用

在多线程领域,所谓堵塞,在某些情况下会挂起线程(即堵塞),一旦条件满足,被挂起的线程又会自动被唤醒。

二、阻塞队列种类分析

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

简单介绍下其中三个队列:

1、ArrayListBlockingQueue

基于数组的阻塞队列,同LinkedBlockingQueue类似,内部维持着一个定长数据缓冲队列(该队列由数组构成)。ArrayBlockingQueue内部还保存着两个整形变量,分别标识着队列的头部和尾部在数组中的位置。
    ArrayBlockingQueue在生产者放入数据和消费者获取数据,都是共用同一个锁对象,由此也意味着两者无法真正并行运行,这点尤其不同于LinkedBlockingQueue;按照实现原理来分析,ArrayBlockingQueue完全可以采用分离锁,从而实现生产者和消费者操作的完全并行运行。Doug Lea之所以没这样去做,也许是因为ArrayBlockingQueue的数据写入和获取操作已经足够轻巧,以至于引入独立的锁机制,除了给代码带来额外的复杂性外,其在性能上完全占不到任何便宜。 ArrayBlockingQueue和LinkedBlockingQueue间还有一个明显的不同之处在于,前者在插入或删除元素时不会产生或销毁任何额外的对象实例,而后者则会生成一个额外的Node对象。这在长时间内需要高效并发地处理大批量数据的系统中,其对于GC的影响还是存在一定的区别。

2、LinkedBlockingQueue

LinkedBlockingQueue默认大小是Integer.MAX_VALUE,可以设定大小,可以理解为一个缓存的有界等待队列。
    基于链表的阻塞队列,内部维持着一个数据缓冲队列(该队列由链表构成)。当生产者往队列中放入一个数据时,队列会从生产者手中获取数据,并缓存在队列内部,而生产者立即返回;只有当队列缓冲区达到最大值缓存容量时(LinkedBlockingQueue可以通过构造函数指定该值),才会阻塞生产者队列,直到消费者从队列中消费掉一份数据,生产者线程会被唤醒,反之对于消费者这端的处理也基于同样的原理。
    LinkedBlockingQueue之所以能够高效的处理并发数据,还因为其对于生产者端和消费者端分别采用了独立的锁来控制数据同步,这也意味着在高并发的情况下生产者和消费者可以并行地操作队列中的数据,以此来提高整个队列的并发性能。

3、SynchronousQueue

SynchronousQueue是无界的,是一种无缓冲的等待队列,但是由于该Queue本身的特性,在某次添加元素后必须等待其他线程取走后才能继续添加;可以认为SynchronousQueue是一个缓存值为1的阻塞队列,但是 isEmpty()方法永远返回是true,remainingCapacity() 方法永远返回是0,remove()和removeAll() 方法永远返回是false,iterator()方法永远返回空,peek()方法永远返回null。
    声明一个SynchronousQueue有两种不同的方式,它们之间有着不太一样的行为。公平模式和非公平模式的区别:如果采用公平模式:SynchronousQueue会采用公平锁,并配合一个FIFO队列来阻塞多余的生产者和消费者,从而体系整体的公平策略;但如果是非公平模式(SynchronousQueue默认):SynchronousQueue采用非公平锁,同时配合一个LIFO队列来管理多余的生产者和消费者,而后一种模式,如果生产者和消费者的处理速度有差距,则很容易出现饥渴的情况,即可能有某些生产者或者是消费者的数据永远都得不到处理。

三、非阻塞队列

基于锁的算法会带来一些活跃度失败的风险。如果线程在持有锁的时候因为阻塞I/O,页面错误,或其他原因发生延迟,很可能所有的线程都不能前进了。 一个线程的失败或挂起不应该影响其他线程的失败或挂起,这样的算法成为非阻塞(nonblocking)算法;如果算法的每一个步骤中都有一些线程能够继续执行,那么这样的算法称为锁自由(lock-free)算法。在线程间使用CAS进行协调,这样的算法如果能构建正确的话,它既是非阻塞的,又是锁自由的。非竞争的CAS总是能够成功,如果多个线程以一个CAS竞争,总会有一个胜出并前进。

非阻塞算法通过使用低层次的并发原语,比如比较交换,取代了锁。原子变量类向用户提供了这些底层级原语,也能够当做“更佳的volatile变量”使用,同时提供了整数类和对象引用的原子化更新操作。

-----摘自微信公众号 - Java编程指南(JavaXxzyfx),作者:程序员龙猫

基于链接节点的、无界的、线程安全。此队列按照 FIFO(先进先出)原则对元素进行排序。队列的头部 是队列中时间最长的元素。队列的尾部 是队列中时间最短的元素。新的元素插入到队列的尾部,队列检索操作从队列头部获得元素。当许多线程共享访问一个公共 collection 时,ConcurrentLinkedQueue 是一个恰当的选择。此队列不允许 null 元素。

入队和出队操作均利用CAS(compare and set)更新,这样允许多个线程并发执行,并且不会因为加锁而阻塞线程,使得并发性能更好。

在并发编程中,一般推荐使用阻塞队列,这样实现可以尽量地避免程序出现意外的错误。阻塞队列使用最经典的场景就是socket客户端数据的读取和解析,读取数据的线程不断将数据放入队列,然后解析线程不断从队列取数据解析。还有其他类似的场景,只要符合生产者-消费者模型的都可以使用阻塞队列。

使用非阻塞队列,虽然能即时返回结果(消费结果),但必须自行编码解决返回为空的情况处理(以及消费重试等问题)。

另外他们都是线程安全的,不用考虑线程同步问题。

java之阻塞队列和非阻塞队列相关推荐

  1. 让人一看就会的java阻塞队列与非阻塞队列

    队列介绍 今天要来讲一下java里的队列,队列,顾名思义,排队的列,既然按排队形来做的话,生活中的银行排队啊,上车排队啊,都是先到先办理或者先上车,队列存取数据列也一样,这就是先进先出,使用队列的规则 ...

  2. 阻塞队列和非阻塞队列(JAVA)

    文章目录 1.阻塞队列 1.1 代码举例 1.2 LinkedBlockingQueue 2.非阻塞队列 2.1 代码举例 2.2 ConcurrentLinkedQueue 1.阻塞队列 1.1 代 ...

  3. 阻塞队列和非阻塞队列

    1.阻塞队列和非阻塞队列的区别:阻塞队列可以阻塞,非阻塞队列不能阻塞,只能使用队列wait(),notify()进行队列消息传送.而阻塞队列当队列里面没有值时,会阻塞直到有值输入.输入也一样,当队列满 ...

  4. 同步阻塞、同步非阻塞、异步阻塞、异步非阻塞与 I/O 多路复用、Java NIO 之间的联系

    同步阻塞.同步非阻塞.异步阻塞.异步非阻塞与 I/O 多路复用.Java NIO 之间的联系 先验知识 此处的异步指的是什么 同步.异步.阻塞.非阻塞 同步阻塞.同步非阻塞.异步阻塞.异步非阻塞 一个 ...

  5. java非阻塞io流_阻塞式和非阻塞io流初认识

    1  什么是阻塞式和非阻塞式? 阻塞式IO:IO即input/output,阻塞式IO指的是"一旦输入/输出工作没有完成,则程序阻塞,直到输入/输出工作完成".在目前,我们从书本上 ...

  6. 阻塞io阻塞io_Redis:RESP协议,阻塞IO 与非阻塞IO,Redis的线程模型

    1.Redis 阻塞IO 与非阻塞IO Java在JDK1.4 中引入了NIO ,但是也有很多人在使用阻塞IO,这两种IO有什么区别? 在阻塞模式下,如果你从数据流读取不到指定大小的数据量,IO就会阻 ...

  7. 阻塞式和非阻塞式udp传输_NIO非阻塞网络编程三大核心理念

    本次开始NIO网络编程,之前已经说过BIO,对于阻塞IO里面的问题一定有了清晰的认识,在JDK1.4版本后,提供了新的JAVA IO操作非阻塞API,用意替换JAVA IO 和JAVA NetWork ...

  8. 阻塞IO、非阻塞IO、以及多路复用原理

    阻塞IO.非阻塞IO.以及多路复用原理 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 阻塞IO.非阻塞IO.以及多路复用原理 什么是I/O 一.BIO(阻塞IO) 二.N ...

  9. 嵌入式驱动之阻塞操作、非阻塞操作

    阻塞 阻塞操作     是指在执行设备操作时若不能获得资源则挂起进程,直到满足可操作的条件后再进行操作. 被挂起的进程进入休眠状态,被从调度器的运行队列移走,直到等待的条件被满足. 非阻塞操作   进 ...

最新文章

  1. JavaHelp软件的一个定制实用程序类
  2. mac os系统使用Visual Studio Code打开浏览器查看HTML文件
  3. jquery常用功能
  4. 运行时类加载以支持不断变化的API
  5. Win32API 数据基本类型
  6. “韩国泡菜源于中国”说引韩国教授抗议,要求修改词条,百度百科回应...
  7. pycharm远程开发
  8. 利用python进行数据分析—四、Numpy基础:数组与向量化计算
  9. uva 11426 GCD - Extreme (II)
  10. 修复VC6.0打开菜单项以及添加工程菜单项
  11. 密码学 SM3算法 Python实现
  12. opencv快速下载
  13. Android之Handler机制使用实例
  14. 游戏开发计划——数据元素设计(技能)
  15. 获取Winform窗体或Panel下包含的所有控件、根据控件名称获取指定控件
  16. perl读取文件夹下的文件
  17. 从GraalVM到Quarkus系列-B002篇-Quarkus中的字节码框架gizmo
  18. 第五代TTS语音芯片SYN8086性能再突破
  19. MATLAB 2021a+ MAC
  20. “区块链+物流运输业”能融合发展吗?

热门文章

  1. Who Am I ?
  2. 绝对定位和相对定位的区别?
  3. 佳和她的四合院 像老北京一样生活
  4. comodo泛域名证书与comodo多域名证书选择
  5. pinpoint 安装 for spring cloud
  6. 终于有人把P2P、P2C、O2O、B2C、B2B、C2C 的区别讲透了
  7. 空气的导热性真差啊。。。
  8. 【android开发中的小技巧-1】
  9. 副卡显示无服务器,手机玩游戏时副卡无服务或收不到电话、短信怎么回事?
  10. 全面进军国际市场?酷派的手机“野心”拿什么来实现