基于数组的有界阻塞队列 —— ArrayBlockingQueue
前言
在阅读完和 AQS 相关的锁以及同步辅助器之后,来一起阅读 JUC 下的和队列相关的源码。先从第一个开始:ArrayBlockingQueue。
公众号:liuzhihangs,记录工作学习中的技术、开发及源码笔记;时不时分享一些生活中的见闻感悟。欢迎大佬来指导!
介绍
由数组支持的有界BlockingQueue阻塞队列。
这个队列的命令元素FIFO(先入先出)。 队列的头是元素一直在队列中时间最长。 队列的尾部是该元素已经在队列中的时间最短。 新元素插入到队列的尾部,并且队列检索操作获取在队列的头部元素。
这是一个典型的“有界缓冲区”,在其中一个固定大小的数组保持由生产者插入并受到消费者的提取的元素。 一旦创建,容量不能改变。 试图put 一个元素到一个满的队列将导致操作阻塞; 试图 take 从空队列一个元素将类似地阻塞。
此类支持订购等待生产者和消费者线程可选的公平政策。 默认情况下,这个顺序不能保证。 然而,队列公平设置为构建 true 保证线程以FIFO的顺序进行访问。 公平性通常会降低吞吐量,但减少了可变性和避免饥饿。
基本使用
demo 只是临时写的一个,很简单的版本。
问题疑问
ArrayBlockingQueue 的实现原理是什么?
入队列和出队列方法之间的区别是什么?
源码分析
基本结构
参数介绍
构造函数
添加元素
add 方法:调用的是父类 AbstractQueue 的 add 方法,内部调用的是 offer 方法,如果 offer 返回 false,则抛出异常。
offer 方法:校验元素非空,加互斥锁,如果队列满了,则返回 false,如果队列未满,则调用 enqueue 方法,添加元素。
put 方法:校验元素非空,加互斥锁,如果队列满了,则一直自旋等待,队列未满则调用 enqueue 方法,添加元素。
所以下面还是需要看一下 enqueue 方法:
获取元素
通过源码可以看出:
pool 和 take 都是从队列中获取元素,二者不同的是,当队列中没有元素时,poll 方法返回 null,而 take 方法会一直阻塞等待,直到从队列中获取到元素。
poll 和 take 方法获取元素都是调用的 dequeue 方法。
查看元素
总结
Q&A
Q: ArrayBlockingQueue 的实现原理?
A: ArrayBlockingQueue 是基于数组实现的,内部使用 ReentrantLock 互斥锁,防止并发放置元素或者取出元素的冲突问题。
Q: 入队列和出队列方法之间的区别是什么?
结束语
ArrayBlockingQueue 中使用了 ReentrantLock 互斥锁,在元素入队列和出队列的时候都进行了加锁,所以同时只会有一个线程进行入队列或者出队列,从而保证线程安全。
版权声明: 本文为 InfoQ 作者【liuzhihang】的原创文章。
原文链接:【http://xie.infoq.cn/article/87bec77524d9d739b58c50ee5】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论