LinkedBlockingQueue
一個基於鏈表的阻塞隊列。此隊列按 FIFO(先進先出)排序元素
public LinkedBlockingQueue() {
//默認最大容量
this(Integer.MAX_VALUE);
}
public LinkedBlockingQueue(int capacity) {
if (capacity <= 0) throw new IllegalArgumentException();
this.capacity = capacity;
//維護雙端隊列
last = head = new Node<E>(null);
}
put
//put將指定元素插入此隊列尾部,將等待可用的空間
public void put(E e) throws InterruptedException {
if (e == null) throw new NullPointerException();
// Note: convention in all put/take/etc is to preset local var
// holding count negative to indicate failure unless set.
int c = -1;
//創建新節點
Node<E> node = new Node<E>(e);
//獲取put鎖
final ReentrantLock putLock = this.putLock;
final AtomicInteger count = this.count;
//如果當前線程未被中斷,則獲取鎖。
putLock.lockInterruptibly();
try {
//達到上限容量,則一直等待
while (count.get() == capacity) {
notFull.await();
}
//設置值
enqueue(node);
c = count.getAndIncrement();
if (c + 1 < capacity)
//列是否有可用空間,如果有則喚醒一個等待線程
notFull.signal();
} finally {
//釋放鎖
putLock.unlock();
}
// 如果隊列中有一條數據,喚醒消費線程進行消費
if (c == 0)
signalNotEmpty();
}
offer
public boolean offer(E e) {
if (e == null) throw new NullPointerException();
//等於最大容量,則返回,而不阻塞
final AtomicInteger count = this.count;
if (count.get() == capacity)
return false;
int c = -1;
Node<E> node = new Node<E>(e);
final ReentrantLock putLock = this.putLock;
//因爲不阻塞,所以直接獲取鎖
putLock.lock();
try {
//再次檢查容量大小,然後直接添加,隨後喚醒一個等待線程
if (count.get() < capacity) {
enqueue(node);
c = count.getAndIncrement();
if (c + 1 < capacity)
notFull.signal();
}
} finally {
putLock.unlock();
}
// 如果隊列中有一條數據,喚醒消費線程進行消費
if (c == 0)
signalNotEmpty();
return c >= 0;
}
阻塞時間的offer
public boolean offer(E e, long timeout, TimeUnit unit)
throws InterruptedException {
if (e == null) throw new NullPointerException();
long nanos = unit.toNanos(timeout);
int c = -1;
final ReentrantLock putLock = this.putLock;
final AtomicInteger count = this.count;
//獲取中斷鎖
putLock.lockInterruptibly();
try {
//等於最大容量,則一直循環
while (count.get() == capacity) {
//超過超時時間則返回
if (nanos <= 0)
return false;
//當前線程在接到信號、被中斷或到達指定等待時間之前一直處於等待狀態。
nanos = notFull.awaitNanos(nanos);
}
enqueue(new Node<E>(e));
c = count.getAndIncrement();
//通知信號
if (c + 1 < capacity)
notFull.signal();
} finally {
putLock.unlock();
}
// 如果隊列中有一條數據,喚醒消費線程進行消費
if (c == 0)
signalNotEmpty();
return true;
}
take
//獲取並移除此隊列的頭部,在元素變得可用之前一直等待
public E take() throws InterruptedException {
E x;
int c = -1;
final AtomicInteger count = this.count;
final ReentrantLock takeLock = this.takeLock;
//中斷點
takeLock.lockInterruptibly();
try {
//隊列爲空,阻塞等待
while (count.get() == 0) {
notEmpty.await();
}
//獲取值
x = dequeue();
c = count.getAndDecrement();
// 隊列中還有元素,喚醒下一個消費線程進行消費
if (c > 1)
notEmpty.signal();
} finally {
takeLock.unlock();
}
// 之前隊列是滿的,則喚醒生產線程進行添加元素
if (c == capacity)
signalNotFull();
return x;
}
private E dequeue() {
// assert takeLock.isHeldByCurrentThread();
// assert head.item == null;
//head默認root的value是null
Node<E> h = head;
Node<E> first = h.next;
// head節點原來指向的節點的next指向自己,等待下次gc回收
h.next = h; // help GC
// head節點指向下一個節點
head = first;
//獲取新的head的value
E x = first.item;
//新的head設置null
first.item = null;
return x;
}
poll
public E poll() {
final AtomicInteger count = this.count;
//容量爲0,直接返回
if (count.get() == 0)
return null;
E x = null;
int c = -1;
final ReentrantLock takeLock = this.takeLock;
takeLock.lock();
try {
if (count.get() > 0) {
x = dequeue();
c = count.getAndDecrement();
if (c > 1)
notEmpty.signal();
}
} finally {
takeLock.unlock();
}
if (c == capacity)
signalNotFull();
return x;
}
peek
public E peek() {
if (count.get() == 0)
return null;
final ReentrantLock takeLock = this.takeLock;
takeLock.lock();
try {
Node<E> first = head.next;
if (first == null)
return null;
else
return first.item;
} finally {
takeLock.unlock();
}
}
remove
public boolean remove(Object o) {
//爲null,直接返回
if (o == null) return false;
//put和take鎖,就暫時不能新增或修改
fullyLock();
try {
for (Node<E> trail = head, p = trail.next;
p != null;
trail = p, p = p.next) {
//匹配到值,則刪除
if (o.equals(p.item)) {
unlink(p, trail);
return true;
}
}
return false;
} finally {
//釋放2個鎖
fullyUnlock();
}
}
void unlink(Node<E> p, Node<E> trail) {
// assert isFullyLocked();
// p.next is not changed, to allow iterators that are
// traversing p to maintain their weak-consistency guarantee.
p.item = null;
//在迭代的時候,如果p.next爲null,則會造成異常.所以這裏沒設置null
trail.next = p.next;
if (last == p)
last = trail;
// 如果刪除之前元素是滿的,刪除之後就有空間了,喚醒生產線程放入元素
if (count.getAndDecrement() == capacity)
notFull.signal();
}
迭代器
當執行迭代器的nextNode的時候,如果同時發現有執行take操作,因爲當前head.next指向了自己,
private Node<E> nextNode(Node<E> p) {
for (;;) {
Node<E> s = p.next;
//take時,head.next=head,則直接返回當前head的下一個節點
if (s == p)
return head.next;
if (s == null || s.item != null)
return s;
p = s;
}
}
總結
底層阻塞隊列FIFO.內部由兩個ReentrantLock來實現出入隊列的線程安全,由各自的Condition對象的await和signal來實現等待和喚醒功能。
默認容量無界,且底層鏈表,所以執行插入和刪除效率比較高.且2把鎖維護新增刪除,所以併發有所提高.