一、什麼是阻塞隊列
阻塞隊列是一個隊列,在數據結構中起的作用如下圖:
棧:先進後出,後進先出
隊列:先進先出
阻塞:必須要阻塞/不得不阻塞
當隊列是空的,從隊列中獲取元素的操作將會被阻塞
當隊列是滿的,從隊列中添加元素的操作將會被阻塞
試圖從空的隊列中獲取元素的線程將會被阻塞,直到其他線程往空的隊列插入新的元素
試圖向已滿的隊列中添加新元素的線程將會被阻塞,直到其他線程從隊列中移除一個或多個元素或者完全清空,使隊列變得空閒起來並後續新增
二、阻塞隊列的作用
在多線程領域:所謂阻塞,在某些情況下會掛起線程(即阻塞),一旦條件滿足,被掛起的線程又會自動被喚起
2.1 爲什麼需要BlockingQueue
好處是我們不需要關心什麼時候需要阻塞線程,什麼時候需要喚醒線程,因爲這一切BlockingQueue都給你一手包辦了
在concurrent包發佈以前,在多線程環境下,我們每個程序員都必須去自己控制這些細節,尤其還要兼顧效率和線程安全,而這會給我們的程序帶來不小的複雜度。
2.2 阻塞隊列的分類
ArrayBlockingQueue:由數組結構組成的有界阻塞隊列
LinkedBlockingQueue:由鏈表結構組成的有界(但大小默認值爲integer.MAX_VALUE)阻塞隊列
PriorityBlockingQueue:支持優先級排序的無界阻塞隊列
DelayQueue:使用優先級隊列實現的延遲無界阻塞隊列
SynchronousQueue:不存儲元素的阻塞隊列,也即單個元素的隊列
LinkedTransferQueue:由鏈表組成的無界阻塞隊列
LinkedBlockingDeque:由鏈表組成的雙向阻塞隊列
2.3 BlockingQueue核心方法
| 拋出異常 | 當阻塞隊列滿時,再往隊列裏add插入元素會拋IllegalStateException:Queue full
當阻塞隊列空時,再往隊列裏remove移除元素會拋NoSuchElementException |
|特殊值|插入方法,成功ture失敗false
移除方法,成功返回出隊列的元素,隊列裏沒有就返回null|
| 一直阻塞 | 當阻塞隊列滿時,生產者線程繼續往隊列裏put元素,隊列會一直阻塞生產者線程直到put數據or響應中斷退出
當阻塞隊列空時,消費者線程試圖從隊列裏take元素,隊列會一直阻塞消費者線程直到隊列可用 |
| 超時退出 | 當阻塞隊列滿時,隊列會阻塞生產者線程一定時間,超過限時後生產者線程會退出 |
三、使用示例
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
/**
* 阻塞隊列
*/
public class BlockingQueueDemo {
public static void main(String[] args) throws InterruptedException {
// List list = new ArrayList();
BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(3);
//第一組
// System.out.println(blockingQueue.add("a"));
// System.out.println(blockingQueue.add("b"));
// System.out.println(blockingQueue.add("c"));
// System.out.println(blockingQueue.element());
//System.out.println(blockingQueue.add("x"));
// System.out.println(blockingQueue.remove());
// System.out.println(blockingQueue.remove());
// System.out.println(blockingQueue.remove());
// System.out.println(blockingQueue.remove());
// 第二組
// System.out.println(blockingQueue.offer("a"));
// System.out.println(blockingQueue.offer("b"));
// System.out.println(blockingQueue.offer("c"));
// System.out.println(blockingQueue.offer("x"));
// System.out.println(blockingQueue.poll());
// System.out.println(blockingQueue.poll());
// System.out.println(blockingQueue.poll());
// System.out.println(blockingQueue.poll());
// 第三組
// blockingQueue.put("a");
// blockingQueue.put("b");
// blockingQueue.put("c");
// //blockingQueue.put("x");
// System.out.println(blockingQueue.take());
// System.out.println(blockingQueue.take());
// System.out.println(blockingQueue.take());
// System.out.println(blockingQueue.take());
// 第四組
System.out.println(blockingQueue.offer("a"));
System.out.println(blockingQueue.offer("b"));
System.out.println(blockingQueue.offer("c"));
System.out.println(blockingQueue.offer("a",3L, TimeUnit.SECONDS));
}
}