Java 線程池的各個參數的含義
文章目錄
1.線程池參數
參數名 | 含義 |
---|---|
corePoolSize | 核心線程數 |
maximumPoolSize | 最大線程數 |
keepAliveTime+時間單位 unit | 空閒線程的存活時間 |
ThreadFactory | 線程工廠,用來創建新線程 |
workQueue | 用於存放任務的隊列 |
Handler | 處理被拒絕的任務 |
2.線程池執行流程
2.1 流程圖
2.2 線程創建的流程
- 當任務提交之後,線程池首先會檢查當前線程數,如果當前的線程數小於核心線程數(corePoolSize),比如最開始創建的時候線程數爲 0,則新建線程並執行任務。
- 當提交的任務不斷增加,創建的線程數等於核心線程數(corePoolSize),新增的任務會被添加到 workQueue 任務隊列中,等待覈心線程執行完當前任務後,重新從 workQueue 中獲取任務執行。
- 假設任務非常多,達到了 workQueue 的最大容量,但是當前線程數小於最大線程數(maximumPoolSize),線程池會在覈心線程數(corePoolSize)的基礎上繼續創建線程來執行任務。
- 假設任務繼續增加,線程池的線程數達到最大線程數(maximumPoolSize),如果任務繼續增加,這個時候線程池就會採用拒絕策略來拒絕這些任務。
2.3 小結
在任務不斷增加的過程中,線程池會逐一判斷
- 核心線程數(corePoolSize)
- 任務隊列(workQueue)
- 最大線程數(maximumPoolSize)
- 拒絕策略
3.核心線程數和最大線程數
corePoolSize 是核心線程數,初始大小是 0,但是在創建線程之後,核心線程會常駐在線程池中,即使沒有任務執行,也不會被銷燬。隨着任務數的增加,當任務隊列(workQueue )滿了之後,線程池根據最大線程數(maximumPoolSize)來創建非核心線程,當任務執行完,線程有空閒,非核心線程會被回收。
“正式員工” 與 “外包員工”
一般大型銀行會有很多項目要做,但是銀行的正式編制有限,這種時候就需要採用“人力外包”的形式。corePoolSize 相當於正式員工,而 (maximumPoolSize - corePoolSize) 相當於外包員工,當項目比較少的時候,正式員工就可以處理,但是項目增多時超過了處理負荷,就需要增加外包人員協助進行處理。
當項目完成或者結束之後,正式員工還是在銀行上班,等待任務或者處理新的任務,而外包人員則會結束和銀行的合同。
4.keepAliveTime+時間單位
第三個參數是 keepAliveTime + 時間單位,當線程池中線程數量多於核心線程數時,而此時又沒有任務可做,線程池就會檢測線程的 keepAliveTime,如果超過規定的時間,無事可做的線程就會被銷燬,以便減少內存的佔用和資源消耗。如果後期任務又多了起來,線程池也會根據規則重新創建線程,所以這是一個可伸縮的過程,比較靈活,我們也可以用 setKeepAliveTime 方法動態改變 keepAliveTime 的參數值。
5.ThreadFactory
ThreadFactory 使用的是抽象工廠模式
第四個參數是 ThreadFactory,ThreadFactory 實際上是一個線程工廠,它的作用是生產線程以便執行任務。我們可以選擇使用默認的線程工廠,創建的線程都會在同一個線程組,並擁有一樣的優先級,且都不是守護線程,我們也可以選擇自己定製線程工廠,以方便給線程自定義命名,不同的線程池內的線程通常會根據具體業務來定製不同的線程名。
爲什麼創建的線程不是守護線程?
- 守護線程:和主線程一起結束的線程,叫守護線程。
- 非守護線程:主線程的結束不影響線程的執行的線程,也叫用戶線程。
源碼如下:
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r,
namePrefix + threadNumber.getAndIncrement(),
0);
if (t.isDaemon())// 判斷是否是守護線程
t.setDaemon(false);// 如果是則設置爲 false
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);// 設置優先級爲 5
return t;
}
有源碼可知,如果線程是守護線程,會重新設置爲非守護線程,而設置爲非守護線程的原因是保證該線程不受主線程的影響。
6.workQueue
阻塞隊列,後續專題章節進行講解
7.Handler
拒絕策略,後續專題章節進行講解
8.參考
- 《Java 併發編程 78 講》- 徐隆曦