ConcurrentLinkedQueue使用和方法介紹


定義

一個基於鏈接節點的無界線程安全隊列。此隊列按照 FIFO(先進先出)原則對元素進行排序。隊列的頭部 是隊列中時間最長的元素。隊列的尾部 是隊列中時間最短的元素。
新的元素插入到隊列的尾部,隊列獲取操作從隊列頭部獲得元素。當多個線程共享訪問一個公共 collection 時,ConcurrentLinkedQueue 是一個恰當的選擇。此隊列不允許使用 null 元素。

offer和poll

offer(E e) 
          將指定元素插入此隊列的尾部。

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() 
          返回以恰當順序包含此隊列所有元素的數組。
<T> T[]
toArray(T[] a) 
          返回以恰當順序包含此隊列所有元素的數組;返回數組的運行時類型是指定數組的運行時類型。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM