LinkedBlockingQueue源码解析
ConcurrentLinkedQueue是通过CAS实现的一个队列,下面我们研究下通过ReentrantLock实现的队列-LinkedBlockingQueue。LinkedBlockingQueue也是使用单向链表实现的,它也有两个Node,分别为head,tail,用来存放首尾节点,并且还有一个初始值为0的原子变量count,用来记录队列元素个数。
另外,LinkedBlockingQueue还有两个ReentrantLock实例,分别用来控制元素入队和出队的原子性,其中takeLock用来控制同时只有一个线程可以从队列头获取元素,putLock控制同时只能有一个线程可以获取锁,在队列尾部添加元素,其他线程必须等待。
notEmpty和notFull是条件变量,它们内部都有一个条件队列用来存放入队和出队时被阻塞的线程。
类图
LinkedBlockingQueue的类图如下所示:
ConcurrentLinkedQueue实现了BlockingQueue接口和继承了AbstractQueue类。
1 | public class LinkedBlockingQueue<E> extends AbstractQueue<E> |
BlockingQueue接口只是定义了一些阻塞队列的公共方法,如下:
1 | public interface BlockingQueue<E> extends Queue<E> { |
AbstractQueue也实现了Queue接口,还提供了某些方法的默认实现
1 | // 从这可以发现,Add方法,其实就是调用的offer方法 |
主要属性
1 | /** The capacity bound, or Integer.MAX_VALUE if none */ |
主要方法
无参构造函数
1 | /** |
生成一个最大为Integer.MAX_VALUE大小的队列,并且生成一个新的值为null的结点,并将head和tail都指向这个null结点。
有参构造函数-指定大小
1 | /** |
生成一个指定大小的队列,并且生成一个新的值为null的结点,并将head和tail都指向这个null结点。
有参构造函数-指定集合
1 | /** |
将队列大小初始化为Integer.MAX_VALUE,申请插入锁,入队列
size方法
1 | /** |
返回原子变量的值
remainingCapacity方法
返回容量减去当前大小的值
1 | /** |
put方法
将元素插入到队列的末尾,如果队列满的话,阻塞当前插入线程,直到有空间插入时
1 | /** |
offer方法
添加一个元素到列表的末尾,如果队列空间满了,则丢弃当前元素
1 | /** |
take方法
从队列中获取一个元素,并从队列中删除该元素,如果队列为空,阻塞当前线程
1 | public E take() throws InterruptedException { |
poll方法
从队列中获取一个元素,并从队列中删除该元素,如果队列为空,直接返回null
1 | public E peek() { |
peek方法
从队列中获取一个元素,如果队列为空,直接返回null
1 | public E peek() { |
remove方法
从队列中删除指定的元素,有返回true,否则返回false
1 | /** |
unlink
1 | /** |
contains方法
1 | /** |