線程池常用的阻塞隊列有哪些?
文章目錄
- 線程池常用的阻塞隊列有哪些?
-
- 1.線程池的内部結構
- 2.阻塞隊列
- 3.LinkedBlockingQueue
- 4.SynchronousQueue
- 5.DelayedWorkQueue
- 6.參考
1.線程池的内部結構
線程池内部由四部分組成
- 第一部分是線程池管理器,主要負責管理線程池的建立、銷毀、添加任務等管理操作。
- 第二部分是工作線程,它又分為核心工作線程和非核心工作線程。
- 第三部分是任務隊列,作為一種緩沖機制,會将超過核心線程數的任務放到任務隊列中,等待執行;由于多線程同時從任務隊列中擷取任務是并發場景,此時就需要任務隊列滿足線程安全的要求,是以線程池中任務隊列采用 BlockingQueue 來保障線程安全。
- 第四部分是任務,任務要求實作統一的接口,以便工作線程可以處理和執行。
2.阻塞隊列
線程池對應的阻塞隊列
線程池 | 阻塞隊列 |
---|---|
FixedThreadPool | LinkedBlockingQueue |
SingleThreadExecutor | LinkedBlockingQueue |
CachedThreadPool | SynchronousQueue |
ScheduledThreadPool | DelayedWorkQueue |
SingleThreadScheduledExecutor | DelayedWorkQueue |
3.LinkedBlockingQueue
第一種阻塞隊列是 LinkedBlockingQueue,它的容量是 Integer.MAX_VALUE,為 231 -1 ,是一個非常大的值,可以認為是無界隊列。
FixedThreadPool 和 SingleThreadExecutor 線程池的線程數是固定的,是以沒有辦法增加特别多的線程來處理任務,這時就需要 LinkedBlockingQueue 這樣一個沒有容量限制的阻塞隊列來存放任務。
4.SynchronousQueue
第二種阻塞隊列是 SynchronousQueue,對應的線程池是 CachedThreadPool。線程池 CachedThreadPool 的最大線程數是 Integer.MAX_VALUE,可以了解為線程數是可以無限擴充的。
CachedThreadPool 和上一種線程池 FixedThreadPool 的情況恰恰相反,FixedThreadPool 的情況是阻塞隊列的容量是無限的,而這裡 CachedThreadPool 是線程數可以無限擴充,是以 CachedThreadPool 線程池并不需要一個任務隊列來存儲任務,因為一旦有任務被送出就直接轉發給線程或者建立新線程來執行,而不需要另外儲存它們。
我們自己建立使用 SynchronousQueue 的線程池時,如果不希望任務被拒絕,那麼就需要注意設定最大線程數要盡可能大一些,以免發生任務數大于最大線程數時,沒辦法把任務放到隊列中也沒有足夠線程來執行任務的情況。
5.DelayedWorkQueue
第三種阻塞隊列是DelayedWorkQueue,它對應的線程池分别是 ScheduledThreadPool 和 SingleThreadScheduledExecutor,這兩種線程池的最大特點就是可以延遲執行任務,比如說一定時間後執行任務或是每隔一定的時間執行一次任務。
DelayedWorkQueue 的特點是内部元素并不是按照放入的時間排序,而是會按照延遲的時間長短對任務進行排序,内部采用的是“堆”的資料結構(堆的應用之一就是 優先級隊列)。之是以線程池 ScheduledThreadPool 和 SingleThreadScheduledExecutor 選擇 DelayedWorkQueue,是因為它們本身正是基于時間執行任務的,而延遲隊列正好可以把任務按時間進行排序,友善任務的執行。
6.參考
- 《Java 并發程式設計 78 講》- 徐隆曦