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

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

- 阻塞方法: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方法增加阻塞时间
