定義
一個基於鏈接節點的無界線程安全隊列。此隊列按照 FIFO(先進先出)原則對元素進行排序。隊列的頭部 是隊列中時間最長的元素。隊列的尾部 是隊列中時間最短的元素。
新的元素插入到隊列的尾部,隊列獲取操作從隊列頭部獲得元素。當多個線程共享訪問一個公共 collection 時,ConcurrentLinkedQueue 是一個恰當的選擇。此隊列不允許使用 null 元素。
offer和poll
poll()
獲取並移除此隊列的頭,如果此隊列為空,則返回 null。
public static void main(String[] args) { ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue(); queue.offer("哈哈哈"); System.out.println("offer后,隊列是否空?" + queue.isEmpty()); System.out.println("從隊列中poll:" + queue.poll()); System.out.println("pool后,隊列是否空?" + queue.isEmpty()); }
offer是往隊列添加元素,poll是從隊列取出元素並且刪除該元素
執行結果
offer后,隊列是否空?false 從隊列中poll:哈哈哈 pool后,隊列是否空?true
ConcurrentLinkedQueue中的add() 和 offer() 完全一樣,都是往隊列尾部添加元素
還有個取元素方法peek
peek()
獲取但不移除此隊列的頭;如果此隊列為空,則返回 null
public static void main(String[] args) { ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue(); queue.offer("哈哈哈"); System.out.println("offer后,隊列是否空?" + queue.isEmpty()); System.out.println("從隊列中peek:" + queue.peek()); System.out.println("從隊列中peek:" + queue.peek()); System.out.println("從隊列中peek:" + queue.peek()); System.out.println("pool后,隊列是否空?" + queue.isEmpty()); }
執行結果:
offer后,隊列是否空?false 從隊列中peek:哈哈哈 從隊列中peek:哈哈哈 從隊列中peek:哈哈哈 pool后,隊列是否空?false
remove
remove(Object o)
從隊列中移除指定元素的單個實例(如果存在)
public static void main(String[] args) { ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue(); queue.offer("哈哈哈"); System.out.println("offer后,隊列是否空?" + queue.isEmpty()); System.out.println("從隊列中remove已存在元素 :" + queue.remove("哈哈哈")); System.out.println("從隊列中remove不存在元素:" + queue.remove("123")); System.out.println("remove后,隊列是否空?" + queue.isEmpty()); }
remove一個已存在元素,會返回true,remove不存在元素,返回false
執行結果:
offer后,隊列是否空?false 從隊列中remove已存在元素 :true 從隊列中remove不存在元素:false remove后,隊列是否空?true
size or isEmpty
size()
返回此隊列中的元素數量
注意:
如果此隊列包含的元素數大於 Integer.MAX_VALUE,則返回 Integer.MAX_VALUE。
需要小心的是,與大多數 collection 不同,此方法不是 一個固定時間操作。由於這些隊列的異步特性,確定當前的元素數需要進行一次花費 O(n) 時間的遍歷。
所以在需要判斷隊列是否為空時,盡量不要用 queue.size()>0,而是用 !queue.isEmpty()
比較size()和isEmpty() 效率的示例:
場景:10000個人去飯店吃飯,10張桌子供飯,分別比較size() 和 isEmpty() 的耗時
public class Test01ConcurrentLinkedQueue { public static void main(String[] args) throws InterruptedException { int peopleNum = 10000;//吃飯人數 int tableNum = 10;//飯桌數量 ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>(); CountDownLatch count = new CountDownLatch(tableNum);//計數器 //將吃飯人數放入隊列(吃飯的人進行排隊) for(int i=1;i<=peopleNum;i++){ queue.offer("消費者_" + i); } //執行10個線程從隊列取出元素(10個桌子開始供飯) System.out.println("-----------------------------------開飯了-----------------------------------"); long start = System.currentTimeMillis(); ExecutorService executorService = Executors.newFixedThreadPool(tableNum); for(int i=0;i<tableNum;i++) { executorService.submit(new Dinner("00" + (i+1), queue, count)); } //計數器等待,知道隊列為空(所有人吃完) count.await(); long time = System.currentTimeMillis() - start; System.out.println("-----------------------------------所有人已經吃完-----------------------------------"); System.out.println("共耗時:" + time); //停止線程池 executorService.shutdown(); } private static class Dinner implements Runnable{ private String name; private ConcurrentLinkedQueue<String> queue; private CountDownLatch count; public Dinner(String name, ConcurrentLinkedQueue<String> queue, CountDownLatch count) { this.name = name; this.queue = queue; this.count = count; } @Override public void run() { //while (queue.size() > 0){ while (!queue.isEmpty()){ //從隊列取出一個元素 排隊的人少一個 System.out.println("【" +queue.poll() + "】----已吃完..., 飯桌編號:" + name); } count.countDown();//計數器-1 } } }
執行結果:
使用size耗時:757ms
使用isEmpty耗時:210
當數據量越大,這種耗時差距越明顯。所以這種判斷用isEmpty 更加合理
contains
contains(Object o)
如果此隊列包含指定元素,則返回 true
public static void main(String[] args) throws InterruptedException { ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue(); queue.offer("123"); System.out.println(queue.contains("123")); System.out.println(queue.contains("234")); }
執行結果:
toArray
toArray()
返回以恰當順序包含此隊列所有元素的數組
toArray(T[] a)
返回以恰當順序包含此隊列所有元素的數組;返回數組的運行時類型是指定數組的運行時類型
public static void main(String[] args) throws InterruptedException { ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<String>(); queue.offer("123"); queue.offer("234"); Object[] objects = queue.toArray(); System.out.println(objects[0] + ", " + objects[1]); //將數據存儲到指定數組 String[] strs = new String[2]; queue.toArray(strs); System.out.println(strs[0] + ", " + strs[1]); }
執行結果:
iterator
iterator()
返回在此隊列元素上以恰當順序進行迭代的迭代器
public static void main(String[] args) throws InterruptedException { ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<String>(); queue.offer("123"); queue.offer("234"); Iterator<String> iterator = queue.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); } }
ConcurrentLinkedQueue文檔說明:
構造方法摘要 | |
---|---|
ConcurrentLinkedQueue() 創建一個最初為空的 ConcurrentLinkedQueue。 |
|
ConcurrentLinkedQueue(Collection<? extends E> c) 創建一個最初包含給定 collection 元素的 ConcurrentLinkedQueue,按照此 collection 迭代器的遍歷順序來添加元素。 |
方法摘要 | ||
---|---|---|
boolean |
add(E e) 將指定元素插入此隊列的尾部。 |
|
boolean |
contains(Object o) 如果此隊列包含指定元素,則返回 true。 |
|
boolean |
isEmpty() 如果此隊列不包含任何元素,則返回 true。 |
|
Iterator<E> |
iterator() 返回在此隊列元素上以恰當順序進行迭代的迭代器。 |
|
boolean |
offer(E e) 將指定元素插入此隊列的尾部。 |
|
E |
peek() 獲取但不移除此隊列的頭;如果此隊列為空,則返回 null。 |
|
E |
poll() 獲取並移除此隊列的頭,如果此隊列為空,則返回 null。 |
|
boolean |
remove(Object o) 從隊列中移除指定元素的單個實例(如果存在)。 |
|
int |
size() 返回此隊列中的元素數量。 |
|
Object[] |
toArray() 返回以恰當順序包含此隊列所有元素的數組。 |
|
|
toArray(T[] a) 返回以恰當順序包含此隊列所有元素的數組;返回數組的運行時類型是指定數組的運行時類型。 |