Java中Queue的3種方式實現方式
時間:2023-06-29 來源:華清遠見
一、隊列的概念
Queue用于模擬隊列這種數據結構,隊列通常是指“先進先出”(FIFO=first in first out)的容器。新元素插入(offer)到隊列的尾部,訪問元素(poll)操作會返回隊列頭部的元素。通常,隊列不允許隨機訪問隊列中的元素。
這種結構就相當于我們排隊上車,先到的站在前面,先上車,后到的得等前面先上車了再上車。
排隊進地鐵站,排隊打飯,排隊買火車票,排隊買東西,排隊辦理銀行業務,排隊…..
Queue的實現方式
二、Java中的Queue的實現有三種方式
阻塞隊列
非阻塞隊列
雙向隊列
Queue 跟 List、Set 一樣,也是繼承了 Collection 接口。既然生活中的“排隊”都那么多,所以Queue的使用場景也是非常多的,很典型的JDK自帶的線程池中就大量使用了Queue來存儲任務。
阻塞隊列
阻塞隊列是一個可以阻塞的先進先出集合,比如某個線程在空隊列獲取元素時、或者在已存滿隊列存儲元素時,都會被阻塞。
說白了就是干等著,啥也干不了。排隊上車的時候,你就只能一直站在在那里排隊,你要是想去上廁所回來你的位置都不見了,還得重新排隊。
BlockingQueue 接口常用的實現類如下:
ArrayBlockingQueue :基于數組的有界阻塞隊列,必須指定大小。
LinkedBlockingQueue :基于單鏈表的無界阻塞隊列,不需指定大小。
PriorityBlockingQueue :基于最小二叉堆的無界、優先級阻塞隊列。
DelayQueue:基于延遲、優先級、無界阻塞隊列。
SynchronousQueue :基于 CAS 的阻塞隊列。
常用方法:
add():新增一個元索,假如隊列已滿,則拋異常。
offer():新增一個元素,假如隊列沒滿則返回 true,假如隊列已滿,則返回 false。
put():新增一個元素,假如隊列滿,則阻塞。
element():獲取隊列頭部一個元素,假如隊列為空,則拋異常。
peek():獲取隊列頭部一個元素,假如隊列為空,則返回 null。
remove():執行刪除操作,返回隊列頭部的元素,假如隊列為空,則拋異常。
poll():執行刪除操作,返回隊列頭部的元素,假如隊列為空,則返回 null。
take():執行刪除操作,返回隊列頭部的元素,假如隊列為空,則阻塞。
非阻塞隊列
非阻塞隊列是使用CAS(compare and set)機制實現,類似 volatile,并發性能好。
人太多了,很多現在開始流行取號,先取個號,看著離我這號太遠了,我出去溜達溜達一下再來。
常用的阻塞隊列有 PriorityQueue 和 ConcurrentLinkedQueue。
PriorityQueue :基于優先級的無界優先級隊列
ConcurrentLinkedDeque:基于雙向鏈表結構的無界并發隊列。
雙端隊列(Deque)
Deque 是一個既可以在頭部操作元素,又可以為尾部操作元素,俗稱為雙向(雙端)隊列。Deque 繼承自 Queue,Deque 實現類有 LinkedList、 ArrayDeque、ConcurrentLinkedDeque 等等。在將List篇的時候,里面就說LinkedList是一種雙向隊列,其實它也是Deque的一種實現方式。
常用雙向對壘的實現類有:
LinkedList:基于單鏈表的無界雙端隊列,允許元素為 null。
ArrayDeque:基于數組的有界雙端隊列,不允許 null。不是線程安全的。當作為棧使用時,性能比Stack好;當作為隊列使用時,性能比LinkedList好。

