Java線程池類型介紹

原文鏈接:https://www.jianshu.com/p/d1ba6a871df8

JDK的線程池相信大家都有用過,它預先創建好一部分線程,使用完後放回池中,避免了創建與銷燬線程的昂貴開銷,使得性能大大提升,和數據庫連接池是一樣的道理,本文簡單介紹一下java中的幾種線程池。

jdk提供了Executors類方便我們創建線程池,我們平時都是使用它的靜態方法newxxxxThreadPool進行線程池的創建。1.8中一共提供了5種線程池。
在這裏插入圖片描述

1.固定數量的線程池

在這裏插入圖片描述
這個比較好理解,即線程的數量是固定的,線程並不會隨着任務的多少而變化。可以發現他最終是通過實例化ThreadPoolExecutor來實現。ThreadPoolExecutor的構造函數有很多參數,每個參數代表的含義是需要了解的,他決定了ThreadPoolExecutor的行爲,我們來看一下他的參數最多的構造函數。

參數最多構造函數:

後倆個參數爲默認值的構造函數:

默認拒絕策略:

corePoolSize:線程池的核心線程數量

maximumPoolSize:線程池中允許的最大線程數

keepAliveTime:當池中線程數大於核心線程數時,該時間爲餘下線程(存活線程總數-核心線程數)的最大空閒存活時間

unit:時間單位

workQueue:工作隊列,存放將要執行的任務的地方

threadFactory:創建線程的線程工廠

handler:達到線程上限或者隊列容量上限時執行的拒絕策略。

這裏需要說明一下線程池的執行行爲。當核心線程未滿時新來任務會創建核心線程,當corePoolSize滿了以後,任務會進入阻塞隊列,只有當阻塞隊列滿了以後,纔會創建非核心線程,當最大線程數與隊列均滿了以後,纔會執行拒絕策略。所以這裏就有一個問題,假如你希望你配置的maximumPoolSize能夠生效,那麼workQueue一定不可以是無界隊列(關於隊列部分會再寫一篇文章)。

我們接着分析FixedThreadPool,通過構造函數我們可以發現,corePoolSize=maximumPoolSize,工作隊列爲LinkedBlockingQueue並且沒有指定容量,即最大容量爲Integer.MAX_VALUE。使用的線程工廠爲默認,使用的拒絕策略也爲默認。拒絕策略這裏也順便說一下,jdk提供了4種拒絕策略。

在這裏插入圖片描述
AbortPolicy:這個比較簡單粗暴,直接拋出異常,也是默認的拒絕策略。

CallerRunsPolicy:直接在調用線程中執行該任務。

DiscardPolicy:直接將該任務丟棄。

DiscardOldestPolicy:丟棄最老的未被執行的任務,並重復入隊操作

2.並行線程池

在這裏插入圖片描述
這個是1.8中新加入的線程池,可以看到主要使用了ForkJoin相關的操作,ForkJoin本人沒有使用過,也比較複雜,這裏就不說了(因爲不會)。

3.只有一個線程的線程池

在這裏插入圖片描述
其實這個可以不稱爲線程池,因爲只有一個線程。核心線程=最大線程=1,這個比較適合需要保證隊列中任務順序執行的場景。

4.緩存線程池

在這裏插入圖片描述
他根據需要創建線程,沒有核心線程,當60s內沒有任務時,將會回收存活的線程,60s內有任務時,他可以重用已有的線程。注意他的工作隊列是SynchronousQueue,這裏簡單的說一下),他的每一個put操作必須等待take操作,這意味着如果任務生產速度大於消費速度,那麼他將不會創建新線程。該線程池適合執行大量小任務的場景。

5.延時線程池

在這裏插入圖片描述
ScheduledThreadPoolExecutor繼承了ThreadPoolExecutor,所以super最終會調到ThreadPoolExecutor的構造函數,可以看到,最大線程數爲int最大值,工作隊列爲延時隊列DelayedWorkQueue,該線程池適合執行延時任務。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章