Java 線程池的各個參數的含義

Java 線程池的各個參數的含義

1.線程池參數

參數名 含義
corePoolSize 核心線程數
maximumPoolSize 最大線程數
keepAliveTime+時間單位 unit 空閒線程的存活時間
ThreadFactory 線程工廠,用來創建新線程
workQueue 用於存放任務的隊列
Handler 處理被拒絕的任務

2.線程池執行流程

2.1 流程圖

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-MDZVKSon-1593035570853)(G:\workspace\csdn\learn-document\java\concurrent\image-20200623162344913.png)]

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

拒絕策略,後續專題章節進行講解

線程池的4種拒絕策略

8.參考

  • 《Java 併發編程 78 講》- 徐隆曦
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章