ArrayBlockingQueue源码解析
2021/6/19 22:56:57
本文主要是介绍ArrayBlockingQueue源码解析,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
注意:在阅读本文之前或在阅读的过程中,需要用到ReentrantLock,内容见《第五章 ReentrantLock源码解析1--获得非公平锁与公平锁lock()》《第六章 ReentrantLock源码解析2--释放锁unlock()》《第七章 ReentrantLock总结》
1、对于ArrayBlockingQueue需要掌握以下几点
- 创建
- 入队(添加元素)
- 出队(删除元素)
2、创建
- public ArrayBlockingQueue(int capacity, boolean fair)
- public ArrayBlockingQueue(int capacity)
使用方法:
- Queue<String> abq = new ArrayBlockingQueue<String>(2);
- Queue<String> abq = new ArrayBlockingQueue<String>(2,true);
通过使用方法,可以看出ArrayBlockingQueue支持ReentrantLock的公平锁模式与非公平锁模式,对于这两种模式,查看本文开头的文章即可。
源代码如下:
View Code View Code注意:
- ArrayBlockingQueue的组成:一个对象数组+1把锁ReentrantLock+2个条件Condition
- 在查看源码的过程中,也要模仿带条件锁的使用,这个双条件锁模式是很经典的模式
3、入队
3.1、public boolean offer(E e)
原理:
- 在队尾插入一个元素, 如果队列没满,立即返回true; 如果队列满了,立即返回false
使用方法:
- abq.offer("hello1");
源代码:
View Code View Code View Code代码非常简单,流程看注释即可,只有一点注意点:
- 在插入元素结束后,唤醒等待notEmpty条件(即获取元素)的线程,可以发现这类似于生产者-消费者模式
3.2、public boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException
原理:
- 在队尾插入一个元素,,如果数组已满,则进入等待,直到出现以下三种情况:
- 被唤醒
- 等待时间超时
- 当前线程被中断
使用方法:
View Code源代码:
View Code注意:
- awaitNanos(nanos)是AQS中的一个方法,这里就不详细说了,有兴趣的自己去查看AQS的源代码。
- lockInterruptibly()与lock()的区别见注释
3.3、public void put(E e) throws InterruptedException
原理:
- 在队尾插入一个元素,如果队列满了,一直阻塞,直到数组不满了或者线程被中断
使用方法:
View Code源代码:
View Code
4、出队
4.1、public E poll()
原理:
- 如果没有元素,直接返回null;如果有元素,将队头元素置null,但是要注意队头是随时变化的,并非一直是items[0]。
使用方法:
abq.poll();
源代码:
View Code View Code
4.2、public E poll(long timeout, TimeUnit unit) throws InterruptedException
原理:
- 从对头删除一个元素,如果数组不空,出队;如果数组已空且已经超时,返回null;如果数组已空且时间未超时,则进入等待,直到出现以下三种情况:
- 被唤醒
- 等待时间超时
- 当前线程被中断
使用方法:
View Code源代码:
View Code
4.3、public E take() throws InterruptedException
原理:
- 将队头元素出队,如果队列空了,一直阻塞,直到数组不为空或者线程被中断
使用方法:
View Code源代码:
View Code
总结:
1、具体入队与出队的原理图:这里只说一种情况,见下图,途中深色部分表示已有元素,浅色部分没有元素。
上面这种情况是怎么形成的呢?当队列满了,这时候,队头元素为items[0]出队了,就形成上边的这种情况。
假设现在又要出队了,则现在的队头元素是items[1],出队后就形成下面的情形。
出队后,对头元素就是items[2]了,假设现在有一个元素将要入队,根据inc方法,我们可以得知,他要插入到items[0]去,入队了形成下图:
以上就是整个入队出队的流程,inc方法上边已经给出,这里再贴一遍:
View Code
2、三种入队对比:
- offer(E e):如果队列没满,立即返回true; 如果队列满了,立即返回false-->不阻塞
- put(E e):如果队列满了,一直阻塞,直到数组不满了或者线程被中断-->阻塞
- offer(E e, long timeout, TimeUnit unit):在队尾插入一个元素,,如果数组已满,则进入等待,直到出现以下三种情况:-->阻塞
- 被唤醒
- 等待时间超时
- 当前线程被中断
3、三种出对对比:
- poll():如果没有元素,直接返回null;如果有元素,出队
- take():如果队列空了,一直阻塞,直到数组不为空或者线程被中断-->阻塞
- poll(long timeout, TimeUnit unit):如果数组不空,出队;如果数组已空且已经超时,返回null;如果数组已空且时间未超时,则进入等待,直到出现以下三种情况:
- 被唤醒
- 等待时间超时
- 当前线程被中断
这篇关于ArrayBlockingQueue源码解析的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-26RocketMQ入门指南:搭建与使用全流程详解
- 2024-11-26RocketMQ入门教程:轻松搭建与使用指南
- 2024-11-26手写RocketMQ:从入门到实践的简单教程
- 2024-11-25【机器学习(二)】分类和回归任务-决策树(Decision Tree,DT)算法-Sentosa_DSML社区版
- 2024-11-23增量更新怎么做?-icode9专业技术文章分享
- 2024-11-23压缩包加密方案有哪些?-icode9专业技术文章分享
- 2024-11-23用shell怎么写一个开机时自动同步远程仓库的代码?-icode9专业技术文章分享
- 2024-11-23webman可以同步自己的仓库吗?-icode9专业技术文章分享
- 2024-11-23在 Webman 中怎么判断是否有某命令进程正在运行?-icode9专业技术文章分享
- 2024-11-23如何重置new Swiper?-icode9专业技术文章分享