線程池常用的阻塞隊列有哪些?

線程池常用的阻塞隊列有哪些?

1.線程池的內部結構

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ajtBM5yG-1593035343720)(G:\workspace\csdn\learn-document\java\concurrent\image-20200624165150713.png)]
線程池內部由四部分組成

  • 第一部分是線程池管理器,主要負責管理線程池的創建、銷燬、添加任務等管理操作。

  • 第二部分是工作線程,它又分爲核心工作線程和非核心工作線程。

  • 第三部分是任務隊列,作爲一種緩衝機制,會將超過核心線程數的任務放到任務隊列中,等待執行;由於多線程同時從任務隊列中獲取任務是併發場景,此時就需要任務隊列滿足線程安全的要求,所以線程池中任務隊列採用 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 講》- 徐隆曦
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章