Tomcat深入淺出
1、Tomcat的線程池
1.1、基本介紹
Tomcat 線程池是 Tomcat 服務器用于管理和分配線程的一種機制。在處理客戶端請求時,Tomcat 會從線程池中獲取線程來執行任務,而不是為每個請求都創建一個新的線程。這樣可以有效減少線程創建和銷毀的開銷,提高服務器的性能和資源利用率。
1.2、主要組件
1.2.1、核心線程數(corePoolSize)
這是線程池中的基本線程數量。當有新的請求到來,并且當前線程數量小于核心線程數時,線程池會創建新的線程來處理請求。例如,如果核心線程數設置為 10,那么在最初的 10 個請求到來時,線程池會創建 10 個線程來分別處理這些請求。
在 Tomcat 的默認配置中,核心線程數是 10。
1.2.2、最大線程數(maximumPoolSize)
線程池允許的最大線程數量。當請求數量超過核心線程數,并且隊列已滿時,線程池會繼續創建線程,直到線程數量達到最大線程數。例如,最大線程數設置為 50,在高并發情況下,線程數量可能會從核心線程數逐漸增加到最大線程數來應對大量請求。
Tomcat 線程池默認的最大線程數是200。
1.2.3、隊列(BlockingQueue)
隊列主要用于存放等待線程池中的線程來處理的客戶端請求。當線程池中的所有線程都在忙碌,且尚未達到最大線程數時,新到達的請求會先被放入隊列中等待處理,這可以有效地平滑請求流量的高峰,避免因短時間內大量請求涌入而導致系統崩潰。一旦隊列滿了,并且線程池中的線程數量還未達到最大線程數,Tomcat 就會迅速創建新的線程來處理請求。或者如果線程池中的某個線程被釋放了,該線程會從隊列中獲取等待處理的請求并進行處理。當線程數大于等于核心線程數時,正常情況下只有當隊列已滿時,才會創建新的線程來處理新請求,直到線程數量達到maximumPoolSize。
Tomcat 使用的默認請求隊列是org.apache.tomcat.util.threads.TaskQueue,這個隊列的大小在默認情況下沒有嚴格的限制,不過在實際應用中,會受到 JVM 內存大小等因素的限制。例如,假設 JVM 中除了請求隊列外,還有其他組件占用了一定的內存,剩余內存只夠再容納 100 個請求對象大小的空間。當隊列中的請求數量已經達到這個極限時,并且再加入新請求就可能導致內存溢出,這種情況下隊列實際上已滿。
1.2.4、線程存活時間(keepAliveTime)
當線程池中的線程數量超過核心線程數,并且在一段時間內沒有任務需要處理時,這些多余的線程會在存活時間過后被銷毀。例如,如果存活時間設置為 60 秒,那么當一個線程空閑了 60 秒后,且線程數量大于核心線程數,這個線程就會被銷毀。
Tomcat 線程池默認的線程存活時間是60秒。
1.3、線程工作流程
- 請求到達:當客戶端請求到達 Tomcat 服務器時,首先會檢查線程池中的線程狀態。
- 分配線程:如果有空閑線程(線程數量小于等于核心線程數),則將請求分配給空閑線程進行處理;如果沒有空閑線程,但線程數量小于最大線程數,并且隊列已滿,則創建新的線程來處理請求;如果線程數量達到最大線程數,并且隊列已滿,那么請求可能會被拒絕(根據拒絕策略)。
- 線程回收:在處理完請求后,線程會回到線程池等待下一個任務。如果線程空閑時間超過存活時間,并且線程數量超過核心線程數,那么該線程會被回收。
1.4、線程大小的影響
線程大小的影響對CPU的影響:
- 太大:當最大線程數較大時,在高并發場景下會有更多的線程同時運行。這可能會導致 CPU 使用率大幅上升,因為每個線程都需要占用一定的 CPU 時間片來執行任務。例如,在一個復雜的 Web 應用中,如果最大線程數設置為 500,并且同時有大量請求到來,500 個線程可能會頻繁地爭奪 CPU 資源,使得 CPU 處于高負載狀態。如果 CPU 核心數較少,可能會出現線程頻繁切換的情況,這會消耗額外的 CPU 資源用于上下文切換,從而降低系統的整體性能。
- 太小:反之,若最大線程數設置得較小,如只有 10,在高并發情況下可能無法充分利用 CPU 資源。因為 CPU 可能有足夠的能力處理更多的線程,但由于線程數的限制,請求只能在隊列中等待或者被拒絕,導致系統的吞吐量較低。
1.5、配置與優化
- 根據應用場景配置參數:
- 對于高并發的 Web 應用,如電商網站的促銷活動期間,可以適當增大核心線程數和最大線程數,同時選擇合適的隊列類型和大小,以應對大量的請求。而對于低并發的應用,如企業內部的管理系統,可以設置較小的核心線程數和最大線程數,以避免資源浪費。
- 例如,在一個預估并發請求數在 100 - 200 之間的應用中,可以將核心線程數設置為 50,最大線程數設置為 200,隊列大小設置為 100,這樣在一般情況下,50 個核心線程可以處理大部分請求,當請求增多時,最多可以利用 200 個線程和 100 個隊列位置來處理高峰流量。
- 監控與調整:
- 可以使用 Tomcat 自帶的監控工具或者第三方監控工具(如 JMX)來監控線程池的使用情況,包括線程的數量、隊列的長度、線程的狀態等。根據監控結果,及時調整線程池的參數,以優化服務器的性能。例如,如果發現請求經常被拒絕,可能需要增大最大線程數或隊列大小。
1.6、Tomcat 最大線程數和Java程序創建的線程的關系
事實上,Tomcat 服務器線程池和 Java 程序通過 thread 創建的線程可以理解為互相獨立的。Tomcat 的最大線程數并不影響 Java 程序創建的線程,比如當 Tomcat 服務器線程池最大線程數設為 10 時,通過 Java 創建的線程也可以超過 10。
兩者互相獨立:
兩者之間的聯系:
- 它們都運行在同一個 JVM 進程中,共享系統的 CPU、內存等資源。如果 Java 程序通過
Thread創建了大量的線程,占用了過多的系統資源,可能會導致 Web 服務器線程池的線程獲取資源不足,從而影響 Web 請求的處理性能。例如,當大量的自定義線程進行密集的 CPU 計算時,Web 服務器線程可能會因為 CPU 資源不足而處理請求變慢。

浙公網安備 33010602011771號