我们在说队列顺序的时候,linkedblockingqueue先进先出的顺序,显示和我们常规的先进再出的理念有所不同。这里我们需要深入到linkedblockingqueue的原理中,去讨论这种顺序机制的存在。接下来我们会从其主要属性、构造函数以及继承结构中,为大家找寻linkedblockingqueu的原理。
1.主要属性
// 容量 private final int capacity; // 元素数量 private final AtomicInteger count = new AtomicInteger(); // 链表头 transient Node<E> head; // 链表尾 private transient Node<E> last; // take锁 private final ReentrantLock takeLock = new ReentrantLock(); // notEmpty条件 // 当队列无元素时,take锁会阻塞在notEmpty条件上,等待其它线程唤醒 private final Condition notEmpty = takeLock.newCondition(); // 放锁 private final ReentrantLock putLock = new ReentrantLock(); // notFull条件 // 当队列满了时,put锁会会阻塞在notFull上,等待其它线程唤醒 private final Condition notFull = putLock.newCondition();
(1)capacity,有容量,可以理解为LinkedBlockingQueue是有界队列
(2)head, last,链表头、链表尾指针
(3)takeLock,notEmpty,take锁及其对应的条件
(4)putLock, notFull,put锁及其对应的条件
(5)入队、出队使用两个不同的锁控制,锁分离,提高效率
2.构造函数
public LinkedBlockingQueue() { this(Integer.MAX_VALUE); } // 限制队列容量,并初始化队列的 head 和 last 节点. public LinkedBlockingQueue(int capacity) { if (capacity <= 0) throw new IllegalArgumentException(); this.capacity = capacity; last = head = new Node<E>(null); } // LinkedBlockingQueue(int capacity)初始化,然后加写锁,将集合c一个个入队. public LinkedBlockingQueue(Collection<? extends E> c) { this(Integer.MAX_VALUE); final ReentrantLock putLock = this.putLock; putLock.lock(); // 写锁(以重入锁实现,对队尾的插入进行控制) try { int n = 0; for (E e : c) { // null元素抛出异常 if (e == null) throw new NullPointerException(); if (n == capacity) throw new IllegalStateException("Queue full"); enqueue(new Node<E>(e)); //将元素封装成Node,入队 ++n; } count.set(n); } finally { putLock.unlock(); // 释放 } }
3.继承结构
以上就是linkedblockingqueue在java中的原理展示,我们通过其函数组成和结构示意图,对linkedblockingqueue能够有大体上的了解,尤其是我们说它是链表结构,想必现在大家已经能够理解原理了。