BlockingQueue阻塞隊列
主要應用場景:生産者消費者模型,是線程安全的
阻塞情況:
1、當隊列滿了進行入隊操作
2、當隊列空了的時候進行出隊列操作
四套方法:
BlockingQueue提供了四套方法,分别來進行插入、移除、檢查。每套方法在不能立刻執行時都有不同的反應。
- Throws Exceptions :如果不能立即執行就抛出異常。
- Special Value:如果不能立即執行就傳回一個特殊的值。
- Blocks:如果不能立即執行就阻塞
- Times Out:如果不能立即執行就阻塞一段時間,如果過了設定時間還沒有被執行,則傳回一個值
實作類:
- ArrayBlockingQueue:它是一個有界的阻塞隊列,内部實作是數組,初始化時指定容量大小,一旦指定大小就不能再變。采用FIFO方式存儲元素。
- DelayQueue:阻塞内部元素,内部元素必須實作Delayed接口,Delayed接口又繼承了Comparable接口,原因在于DelayQueue内部元素需要排序,一般情況按過期時間優先級排序。
public interface Delayed extends Comparable<Delayed> {
long getDelay(TimeUnit unit);
}
DalayQueue内部采用PriorityQueue與ReentrantLock實作。
public class DelayQueue<E extends Delayed> extends AbstractQueue<E>
implements BlockingQueue<E> {
private final transient ReentrantLock lock = new ReentrantLock();
private final PriorityQueue<E> q = new PriorityQueue<E>();
...
}
- LinkedBlockingQueue:大小配置可選,如果初始化時指定了大小,那麼它就是有邊界的。不指定就無邊界(最大整型值)。内部實作是連結清單,采用FIFO形式儲存資料。
public LinkedBlockingQueue() {
this(Integer.MAX_VALUE);//不指定大小,無邊界采用預設值,最大整型值
}
- PriorityBlockingQueue:帶優先級的阻塞隊列。無邊界隊列,允許插入null。插入的對象必須實作Comparator接口,隊列優先級的排序規則就是按照我們對Comparable接口的實作來指定的。我們可以從PriorityBlockingQueue中擷取一個疊代器,但這個疊代器并不保證能按照優先級的順序進行疊代。
public boolean add(E e) {//添加方法
return offer(e);
}
public boolean offer(E e) {
if (e == null)
throw new NullPointerException();
final ReentrantLock lock = this.lock;
lock.lock();
int n, cap;
Object[] array;
while ((n = size) >= (cap = (array = queue).length))
tryGrow(array, cap);
try {
Comparator<? super E> cmp = comparator;//必須實作Comparator接口
if (cmp == null)
siftUpComparable(n, e, array);
else
siftUpUsingComparator(n, e, array, cmp);
size = n + 1;
notEmpty.signal();
} finally {
lock.unlock();
}
return true;
}
- SynchronusQueue:隻能插入一個元素,同步隊列,無界非緩存隊列,不存儲元素。
作為BlockingQueue中的一員,SynchronousQueue與其他BlockingQueue有着不同特性:
- SynchronousQueue沒有容量。與其他BlockingQueue不同,SynchronousQueue是一個不存儲元素的BlockingQueue。每一個put操作必須要等待一個take操作,否則不能繼續添加元素,反之亦然。
- 因為沒有容量,是以對應 peek, contains, clear, isEmpty … 等方法其實是無效的。例如clear是不執行任何操作的,contains始終傳回false,peek始終傳回null。
- SynchronousQueue分為公平和非公平,預設情況下采用非公平性通路政策,當然也可以通過構造函數來設定為公平性通路政策(為true即可)。
- 若使用 TransferQueue, 則隊列中永遠會存在一個 dummy node(這點後面詳細闡述)。
SynchronousQueue非常适合做交換工作,生産者的線程和消費者的線程同步以傳遞某些資訊、事件或者任務。