并发包
Queue
接口
BlockingQueue
接口
ArrayBlockingQueue
类图结构
1. ArrayBlockingQueue类中重要的成员变量
items
: 用来存放队列中的元素takeIndex
:出队元素的下标putIndex
:入队元素的下标count
:统计队列元素的个数ReentrantLock
:用来保证线程安全的锁Condition notEmpty
Condition notFull
2. ArrayBlockingQueue类中的构造方法
构造函数必须传入队列大小的参数,所以该类是有界队列,默认的Lock为非公平锁。在构造函数中为成员变量赋初始值。
3. offer
方法
该方法调用 enqueue
方法进行入队操作。
offer方法是在添加元素的时候,如果队列已经满了无法添加的话,会直接返回false。
4. put
方法
在队列的尾部添加元素的时候,如果队列已经满了无法添加的话,会发生阻塞,一直等待空间以便可以加入元素。使用的是Condition来实现的。
这里注意图中使用的是可中断锁:lock.lockInterruptibly()
,但是我们可以从图3中看到,offer
方法使用的却是lock
方法,这是为什么呢?
我的理解是因为调用了条件变量的await()方法,而await()方法会在中断标志设置后抛出InterruptedException异常后退出,所以还不如在加锁的时候先看中断标志是不是被设置了,如果设置了直接抛出InterruptedException异常,就不用再去获取锁了。
上面这段话引用自:并发编程网——作者:加多
5. pool
方法
6. take
方法
看到了await,就说明是线程安全的方法啦!!!!
7. peek
方法
8. size
方法
总结
ArrayBlockingQueue
通过使用全局独占锁
实现同时只能有一个线程进行入队或者出队操作,这个锁的粒度很大。
使用到的锁为:ReentrantLock
、Condition
对于添加元素的三个方法:
add
方法:在添加元素的时候,若超出了队列的长度,会直接抛出异常offer
方法:在添加元素的时候,如果队列满了,会直接返回false
put
方法:在添加元素的时候,如果队列满了会发生阻塞,一直等待空间,以加入元素
对于取出元素的三个方法:
pool
:在取出元素的时候,如果队列为空,则直接返回null
peek
:在取出元素的时候,如果队列为空,则直接返回null
take
:在取出元素的时候,如果队列为空,则阻塞,直到有元素
对于size方法
- ArrayBlockingQueue的size方法的结果是精确的,因为它使用全局锁保证线程安全。
参考并感谢
[1] 并发编程网——作者:加多