目录
阻塞队列,常应用到生产者和消费者模型下,针对java内置的阻塞队列,具体的原理,存储结构,并发控制,本文进行分析和梳理一下。
1.ArrayBlockingQueue
- 数组结构组成的有界阻塞队列,默认非公平模式,可以支持公平模式,注意公平模式,会降低吞吐量。
- 存储结构:数组形式,有界阻塞队列
- 并发控制:采用Lock,condition 对象实现线程通信
2.LinkedBlockingQueue
- 基于链表结构,支持可选的有界或者无界,默认长度是Integer.max。
- 存储结构:单链表
- 并发控制:采用锁分离技术,即put操作和take操作,各用一把lock,减少锁竞争,提升吞吐量
3.PriorityBlockingQueue
优先级排序的无界阻塞队列,默认采用自然顺序升序排序,可以自定义compareTo()排序规则
存储结构:数组形式,通过构建一颗小根堆来实现
并发控制:lock,condition条件对象支持线程通信
4.DelayQueue
- 基于PriorityBlockingQueue实现,支持延迟,无界阻塞队列
- 存储:数组形式,通过构建一颗小根堆来实现
- 并发控制:lock,condition条件对象支持线程通信
- 应用场景:
-
缓存设计,存有效期,获取到说明缓存过期
- 定时任务调度:比如保存当天会执行的任务和执行时间
-
5.SynchronousQueue
不存储任何元素的阻塞队列,生产者将任务直接发给消费者,每一个put操作,必须等待一个take操作,否则不能添加任何元素
存储:单链表
并发控制:cas保证线程安全
6.LinkedTransferQueue
- 可以看作是SynchronousQueue的加强版,LinkedTransferQueue实现了高效的线程间数据传递,支持等待匹配的生产者-消费者模式,
- 特有方法:
transfer()方法,没有消费者时,生产者阻塞
tryTransfer(),没有消费者时,也可立刻返回,不阻塞生产者
- 存储结构:单链表
- 并发控制:CAS模式,高并发场景下表现卓越,且无需担心队列溢出,丰富的方法和良好的可扩展性满足了各种复杂应用场景的需求。
7.LinkedBlockingDeque
- 链表结构组成的双端队列,因为多了一个操作队列的入口,所以多线程同时入队时,减少了一半的竞争。初始化时可以设置容量,防止过度膨胀,可以运用在“工作窃取”模式下。
- 存储结构:双链表
- 并发控制:lock
8.阻塞队列实现原理
如果队列为空,消费者会一直等待,当生产者加元素时,消费者是如何知道队列有数据的呢?
jdk使用通知模式实现,即当生产者向满的队列加元素,会阻塞当前线程,当消费者获取队列里一个元素后,会通知生产者可以再次加入元素了,具体通过Lock对象 创建的Condition 条件对象,线程会阻塞在条件对象的等待队列里面。