【線程池】常用的三種阻塞隊列


簡介

我們在了解完線程池的參數配置常用線程池后發現,每種線程池會根據不同的需求去選擇不同的隊列來存儲線程任務。線程池的對應隊列如下:
image.png

可以看到,五大常用的線程池,會用到三種線程池

LinkedBlockingQueue

LinkedBlockingQueue是一種沒有容量上限的隊列,也就是說,用了這個隊列的線程池,就可以沒有上限的去保存隊列任務。這種需求場景就很符合FixedThreadPool和SingleThreadExecutor,這兩種線程池都有一個相同點,那就是核心線程數和最大線程數是一致的,線程數都固定了,當任務多的時候線程處理不過來的線程就會放到隊列中,這時就需要一個沒有上限的隊列來存儲線程池的任務了。

SynchronousQueue

SynchronousQueue內部結構中沒有存儲隊列的容器,因此沒有辦法去存儲隊列消息,那么就會有人想,不能存儲消息那算哪門子隊列是吧,其實隊列不一定需要會存儲消息,SynchronousQueue雖然不能存儲隊列消息,但是他可以阻塞隊列消息,可以很好的完成中轉消息的用處,接下來我們可以參考下面這段代碼

public class SynchronousQueueDemo {

    public static void main(String[] args) {
        SynchronousQueue<String> queue = new SynchronousQueue<>();

        Thread producer = new Thread(()->{
            int i = 0;
            while (true){
                System.out.println("生產者開始生產消息...");
                String msg = "這是第"+(++i)+"條消息";
                try {
                    int seconds = getRandomSeconds();
                    System.out.println("生產者生產消息花費了"+seconds+"秒");
                    TimeUnit.SECONDS.sleep(seconds);
                    queue.put(msg);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("生產者消息生產完畢...");
            }
        });

        Thread consumer = new Thread(()->{
            while (true){
                System.out.println("消費者開始消費消息...");
                try {
                    System.out.println("消費者消費到消息:"+queue.take());
                    int seconds = getRandomSeconds();
                    System.out.println("消費者消費消息花費了"+seconds+"秒");
                    TimeUnit.SECONDS.sleep(seconds);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        producer.start();
        consumer.start();
    }

    private static int getRandomSeconds(){
        Random random = new Random();
        return random.nextInt(10)+1;
    }
}

生產者會隨機1到10秒去生產消息,消費者也會隨機1到10秒去消費消息,如果當遇到生產者正在生產消息的時候,消費者端就會因為沒有消息消費而阻塞在那里,同理,如果消費者正在消費消息,生產者也會因為隊列沒法存儲消息而阻塞在那里。
像這種場景就很適合CachedThreadPool這樣的線程池,因為CachedThreadPool可以創建的線程數是無限的,也就是說在這個線程池里面,任務隊列能不能存儲消息其實已經變的可有可無了,但是為了提高線程隊列中轉消息的性能,SynchronousQueue就變的更加合適,因為他想對於LinkedBlockingQueue,SynchronousQueue少了去存儲消息的性能消耗,自然的性能就增加了。

DelayedWorkQueue

DelayedWorkQueue的數據結構是采用數組來實現堆,並且內部元素並不是按照放入的時間順序來排序的,而是會按照延遲的時間長短對任務進行排序。我們可以看到ScheduledThreadPool和SingleThreadScheduledExecutor都適用DelayedWorkQueue來存放隊列,其實就是因為他可以按延遲時間長短排序任務執行的特性,來實現線程池定時的功能。


免責聲明!

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



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