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