ThreadPoolExecutor使用簡介

線程池的繼承關係如下圖:

ThreadPoolExecutor使用簡介

線程池的繼承關係圖

頂級對象是Executor接口,這個接口只有一個方法 void execute(Runnable command),線程池的操作方法都定義在ExecutorService子接口中。

ThreadPoolExecutor參數最全的一個構造函數:

<code>public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<runnable> workQueue)/<runnable>/<code>

函數的參數含義如下:

corePoolSize: 線程池核心線程數

maximumPoolSize:線程池最大線程數

keepAliveTime: 空閒線程存活時間

unit: 存活時間單位

workQueue: 線程池所使用的緩衝隊列

threadFactory:線程池創建線程使用的工廠

handler: 線程池對拒絕任務的處理策略


做以下測試,驗證這三個比較常用的參數使用規則:

corePoolSize=2;maximumPoolSize=3;workQueue= new ArrayBlockingQueue<>(1);

threadFactory和handler使用默認值

當線程池中正在運行的線程數(包括空閒線程)小於等於corePoolSize時,新建線程執行任務。

ThreadPoolExecutor使用簡介

創建2個任務

結果分析:

從輸出結果看出,當執行任務1的線程(pool-1-thread-1)執行完成之後,任務2並沒有去複用pool-1-thread-1而是新建線程(pool-1-thread-2)去執行任務。


當池中正在運行的線程數大於corePoolSize時,新插入的任務進入workQueue排隊(如果workQueue長度允許),等待空閒線程來執行

ThreadPoolExecutor使用簡介

創建3個任務

結果分析:

任務3會等待任務1執行完之後(有了空閒線程),才會執行。並沒有新建線程執行任務3,這時maximumPoolSize=3這個參數沒起作用。


當隊列裡的任務數達到上限,並且池中正在運行的線程數小於maximumPoolSize,對於新加入的任務,新建線程。


ThreadPoolExecutor使用簡介

創建4個任務

ThreadPoolExecutor使用簡介

結果分析:

當任務4進入隊列時發現隊列的長度已經到了上限,所以無法進入隊列排隊,而此時正在運行的線程數(corePoolSize=2)小於maximumPoolSize所以新建線程執行該任務。


當隊列裡的任務數達到上限,並且池中正在運行的線程數等於maximumPoolSize,對於新加入的任務,執行拒絕策略(線程池默認的拒絕策略是拋異常)。

ThreadPoolExecutor使用簡介

創建5個任務

ThreadPoolExecutor使用簡介

任務5被拒絕

結果分析:

當任務5加入時,隊列達到上限,池內運行的線程數達到最大,故執行默認的拒絕策略,拋異常。


參數使用總結

1、corePoolSize:

核心線程數,即使處於空閒狀態,也要保留在池中的線程數,除非將allowCoreThreadTimeOut設置為true。當提交一個任務到線程池時,線程池會創建一個新的線程來執行任務,即使其它空閒的線程能夠執行新的任務也會創建線程,等到需要執行的任務數大於corePoolSize時,就不再創建。新的任務將加入BlockingQueue中。

2、maximumPoolSize:

線程池所能容納的最大線程數。如果隊列滿了,並且已創建的線程數小於maximumPoolSize,則線程池會創建新的線程執行任務。如果使用了無界的任務隊列,那麼maximumPoolSize這個參數就沒有效果。

3、keepAliveTime:

線程池的工作線程空閒後,保持的存活時間。如果任務很多,並且執行的時間比較短,可以調大時間,提高線程的利用率。

4、workQueue:

任務隊列。用於保存等待執行的任務的阻塞隊列。常用的有:

(1)ArrayBlockingQueue:一個基於數組結構的有界阻塞隊列,此隊列按FIFO原則對元素進行排序。

(2)LinkedBlockingQueue:一個基於鏈表結構的有界阻塞隊列,此隊列按FIFO原則對元素進行排序。靜態方法Executors.newFixedThreadPool()、Executors.newSingleThreadExecutor()使用了這個隊列。此隊列的默認長度和最大長度為Integer.MAX_VALUE

(3)SynchronousQueue:一個不存儲元素的阻塞隊列。每個插入操作必須等到另一個線程調用移除操作,否則插入操作一直處於阻塞狀態。靜態方法Executors.newCachedThreadPool()使用了這個隊列。

(4)PriorityBlockingQueue:一個具有優先級的無界阻塞隊列。

5、RejectedExecutionHandler

拒絕策略,當提交任務數超過maxmumPoolSize+workQueue之和時,任務會交給RejectedExecutionHandler來處理。Java線程池框架提供4種策略:

(1)CallerRunsPolicy:只用調用者所在線程來運行任務

(2)AbortPolicy:直接拋出異常RejectedExecutionException

(3)DiscardPolicy:不處理

(4)DiscardOldestPolicy:丟棄隊列裡最近的一個任務,並執行當前任務


分享到:


相關文章: