[java基础-集合篇]有界阻塞队列ArrayBlockingQueue源码解析

从源码可知,ArrayBlockingQueue是一个基于数组大小固定的阻塞队列。
且ArrayBlockingQueue获取元素都从头部获取,插入元素都从尾部插入,即ArrayBlockingQueue是单向队列,从一头插入,一头获取。
即ArrayBlockingQueue结构上是单向队列。

ArrayBlockingQueue特点

主要特点如下:
  1. 有界队列:ArrayBlockingQueue 的容量是固定的,不提供扩容方法,可以通过构造函数指定队列的最大容量。如果尝试添加元素导致队列超过最大容量,则会阻塞当前线程,直到队列中有空间为止。
  2. 基于数组实现:内部使用一个固定大小的数组来存储队列中的元素,这使得队列的容量是固定的(没有扩容机制)。且通过各个index属性来快速获取与插入元素。
  3. 公平性选项:在构造 ArrayBlockingQueue 时,可以选择是否启用公平模式,默认非公平。
公平模式下,队列会按照线程请求的先后顺序来分配资源。
而非公平模式则尽可能减少线程等待时间。
  1. 阻塞方法:ArrayBlockingQueue 提供了 put 和 take 等阻塞方法,当队列满或空时,这些方法会阻塞当前线程,直到条件满足为止,通过双条件算法来做同步控制。获取和插入元素都提供了阻塞方法。

ArrayBlockingQueue结构与属性

构造ArrayBlockingQueue时必须指定大小。
源码中有说明,并发控制使用任何教科书中都可以找到的经典双条件算法。

ArrayBlockingQueue方法

ArrayBlockingQueue插入和获取元素都提供了阻塞方法与非阻塞方法。
阻塞方法主要是通过Condition控制当前线程等待、唤醒等待线程来进行。

offer方法-插入(非阻塞)

如果可以立即插入指定的元素,而不会超出队列的容量,则在此队列的尾部插入指定的元素,成功时返回 true ,并且 false 此队列已满。此方法通常比 add方法 更可取。
值得注意的是:在 enqueue 方法中,使用局部变量 final Object[] items = this.items; 而不是直接操作 this.items 。
使用局部变量而不是直接操作类成员变量好处如下:
1、局部变量访问速度更快,类成员变量可能会涉及额外的开销,例如内存屏障或同步。
局部变量通常在栈,而类成员变量在堆,访问局部变量少了堆内存寻址操作,通常快一点。
如果类成员变量是通过同步块或锁保护的,每次访问这些变量时都需要获取和释放锁。这会带来一定的性能开销,尤其是在高并发场景下。将类成员变量赋值给局部变量后,在方法内部使用局部变量可以减少锁的争用,提高程序的执行效率。
2、可以避免意外修改,将修改限于局部
3、表达更清晰

add方法-插入(非阻塞)

add本质也是调用offer,当offer返回false时跑出异常。

put方法-插入(阻塞)

在此队列的尾部插入指定的元素,等待队列已满时空间变为可用空间

poll方法-获取(非阻塞)

检索但不删除此队列的头部,如果此队列为空,则返回 null 。

take方法-获取(阻塞)

检索并删除此队列的头部,必要时等待,直到元素可用。
由源码可知,当队列空时,进行等待。即阻塞

poll方法-获取(阻塞)

检索并删除此队列的头部,并在必要时等待指定的等待时间,以便元素可用
较take方法增加阻塞时间

资料引用(推荐)

5.2   队列 - Hello 算法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值