Java 經典面試題:聊一聊 JUC 下的 LinkedBlockingQueue
阿新 • • 發佈:2020-05-08
本文聊一下 JUC 下的 LinkedBlockingQueue 佇列,先說說 LinkedBlockingQueue 佇列的特點,然後再從原始碼的角度聊一聊 LinkedBlockingQueue 的主要實現~
LinkedBlockingQueue 有以下特點:
- **LinkedBlockingQueue 是阻塞佇列,底層是單鏈表實現的**~
- **元素從佇列尾進隊,從佇列頭出隊,符合FIFO**~
- **可以使用 Collection 和 Iterator 兩個介面的所有操作,因為實現了兩者的介面**~
- **LinkedBlockingQueue 佇列讀寫操作都加了鎖,但是讀寫用的是兩把不同的鎖,所以可以同時讀寫操作**~
LinkedBlockingQueue 佇列繼承了 `AbstractQueue` 類,實現了 `BlockingQueue` 介面,LinkedBlockingQueue 主要有以下介面:
```java
//將指定的元素插入到此佇列的尾部(如果立即可行且不會超過該佇列的容量)
//在成功時返回 true,如果此佇列已滿,則拋IllegalStateException。
boolean add(E e);
//將指定的元素插入到此佇列的尾部(如果立即可行且不會超過該佇列的容量)
// 將指定的元素插入此佇列的尾部,如果該佇列已滿,
//則在到達指定的等待時間之前等待可用的空間,該方法可中斷
boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException;
//將指定的元素插入此佇列的尾部,如果該佇列已滿,則一直等到(阻塞)。
void put(E e) throws InterruptedException;
//獲取並移除此佇列的頭部,如果沒有元素則等待(阻塞),
//直到有元素將喚醒等待執行緒執行該操作
E take() throws InterruptedException;
//獲取並移除此佇列的頭,如果此佇列為空,則返回 null。
E poll();
//獲取並移除此佇列的頭部,在指定的等待時間前一直等到獲取元素, //超過時間方法將結束
E poll(long timeout, TimeUnit unit) throws InterruptedException;
//從此佇列中移除指定元素的單個例項(如果存在)。
boolean remove(Object o);
//獲取但不移除此佇列的頭元素,沒有則跑異常NoSuchElementException
E element();
//獲取但不移除此佇列的頭;如果此佇列為空,則返回 null。
E peek();
```
LinkedBlockingQueue 佇列的讀寫方法非常的多,但是常用的是 `put()`、`take()`方法,因為它們兩是阻塞的,所以我們就從原始碼的角度來聊一聊 LinkedBlockingQueue 佇列中這兩個方法的實現。
先來看看 `put()`方法,原始碼如下:
```java
public void put(E e) throws InterruptedException {
if (e == null) throw new NullPointerException();
// 預先設定 c 的值為 -1,表示失敗
int c = -1;
Node