更多 Java 并發編程方面的文章,請參見文集《Java 并發編程》
在 Java 多線程應用中,隊列的使用率很高,多數生產消費模型的首選數據結構就是隊列(先進先出)。
Java提供的線程安全的 Queue 可以分為
-
阻塞隊列,典型例子是
LinkedBlockingQueue
- 適用阻塞隊列的好處:多線程操作共同的隊列時不需要額外的同步,另外就是隊列會自動平衡負載,即那邊(生產與消費兩邊)處理快了就會被阻塞掉,從而減少兩邊的處理速度差距。
-
非阻塞隊列,典型例子是
ConcurrentLinkedQueue
- 當許多線程共享訪問一個公共集合時,
ConcurrentLinkedQueue
是一個恰當的選擇。
- 當許多線程共享訪問一個公共集合時,
LinkedBlockingQueue
多用于任務隊列
ConcurrentLinkedQueue
多用于消息隊列
單生產者,單消費者 用 LinkedBlockingqueue
多生產者,單消費者 用 LinkedBlockingqueue
單生產者 ,多消費者 用 ConcurrentLinkedQueue
多生產者 ,多消費者 用 ConcurrentLinkedQueue
LinkedBlockingQueue
由于 LinkedBlockingQueue
實現是線程安全的,實現了先進先出等特性,是作為生產者消費者的首選,LinkedBlockingQueue
可以指定容量,也可以不指定,不指定的話,默認最大是 Integer.MAX_VALUE
。
-
void put(E e)
: 在隊尾插入元素,方法在隊列滿的時候會阻塞直到有隊列成員被消費 -
boolean offer(E e)
: 在隊尾插入元素,方法在隊列滿的時候不會阻塞,直接返回false
-
E take()
: 取出并刪除隊列中的首元素,如果隊列為空,會阻塞,直到有隊列成員被放進來 -
E poll()
: 取出并刪除隊列中的首元素,如果隊列為空,則返回null
,不進行阻塞 -
E peek()
: 取出第一個元素但是不刪除它,沒有就返回null
具體使用參見 Java 通過阻塞隊列實現生產者消費者模式
ConcurrentLinkedQueue
ConcurrentLinkedQueue
是 Queue
的一個安全實現。Queue
中元素按 FIFO 原則進行排序。采用 CAS操作,來保證元素的一致性。
-
boolean offer(E e)
: 在隊尾插入元素,不進行阻塞 -
E poll()
: 取出并刪除隊列中的首元素,不進行阻塞 -
E peek()
: 取出第一個元素但是不刪除它,不進行阻塞
引用:
java挑戰高并發(14): LinkedBlockingQueue和ConcurrentLinkedQueue的區別及用法
并發隊列ConcurrentLinkedQueue和阻塞隊列LinkedBlockingQueue使用場景總結