Tomcat修正JDK原生執行緒池bug的實現原理

2022-09-21 11:00:09 字數 2243 閱讀 9503

為提高處理能力和併發度,web容器一般會把處理請求的任務放到執行緒池,而jdk的原生執行緒池先天適合cpu密集型任務,於是tomcat改造之。

其實threadpoolexecutor的引數主要有如下關鍵點:

限制執行緒個數

限制佇列長度

而tomcat對這倆資源都需要限制,否則高併發下cpu、記憶體都有被耗盡可能。

因此tomcat的執行緒池傳參:

// 定製的任務佇列

taskqueue = new taskqueue(maxqueuesize);

// 定製的執行緒工廠

taskthreadfactory tf = new task程式設計客棧threadfactory(nameprefix,

daemon,

getthreadpriority()

);// 定製執行緒池

executor = new threadpoolexecutor(getminsparethreads(),

getmaxthreads(),

maxidletime,

timeunit.milliseconds,

taskqueue,

tf);

www.cppcns.comtomcat對執行緒數也有限制,設定:

tomcat執行緒池還有自己的特色任務處理流程,通過重寫execute方法實現了自己的特色任務處理邏輯:

和 jdk 執行緒池的區別就在step3,tomcat**程總數達到最大數時,不是立即執行拒絕策略,而是再嘗試向任務佇列新增任務,新增失敗後再執行拒絕策略。

具體又是如何實現的呢?

public void execute(runnable command, long timeout, timeunit unit) catch (rejectedexecutionexception rx)

程式設計客棧 } }}

程式設計客棧}

tomcat執行緒池的execute方法第一行:

submittedcount.incrementandget();

任務執行失敗,拋異常時,將該計數器減一:

submittedcount.decrementandget();

tomcat執行緒池使用submittedcount變數維護已提交到執行緒池,但未執行完的任務數量。

為何要維護這樣乙個變數呢?

tomcat的任務佇列taskqueue擴充套件了jdk的linkedblockingqueue,tomcat給了它乙個capacity,傳給父類linkedblockingqueue的構造器。

public class taskqueue extends linkedblockingqueue

...}

capacity引數通過tomcat的maxqueuesize引數設定,但maxqueuesize預設值integer.max_value:當前執行緒數達到核心執行緒數後,再來任務的話執行緒池會把任務新增到任務佇列,並且總會成功,就永遠無機會建立新執行緒了。

為解決該問題,taskqueue重寫了linkedblockingqueue#offer,在合適時機返回false,表示任務新增失敗,這時執行緒池就會建立新執行緒。

什麼叫合適時機?

public www.cppcns.comclass taskqueue extends linkedblockingqueue {

...@override

// 執行緒池呼叫任務佇列的方法時,當前執行緒數 > core執行緒數

public boolean offer(runnable o) {

// 若執行緒數已達max,則不能建立新執行緒,只能放入任務佇列

if (parent.getpoolsize() == parent.getmaximumpoolsize())

return super.offer(o);

// 至此,表明 max執行緒數 > 當前執行緒數 > core執行緒數

// 說明可建立新執行緒:

// 1. 若已提交任務數 < 當前執行緒數

// 表明還有空閒執行緒,無需建立新執行緒

if (parent.getsubmittedcount()<=(parent.getpoolsize()))

return super.offer(o);

// 2. 若已提交任務數 > 當前執行緒數

// 執行緒不夠用了,返回false去建立新執行緒

if (parent.getpoolsize()

所以tomcat維護已提交任務數是為了在任務佇列長度無限時,讓執行緒池還能有機會建立新執行緒。

tomcat優化jdk原生的執行緒池

佇列進行定製為taskqueue public void execute runnable command,long timeout,timeunit unit catch rejectedexecutionexception rx catch interruptedexception x else...

Tomcat指定jdk 執行

取這個標題是為了更多的人能看到這個部落格,其實tomcat執行只要jre就可以了,所有我們只要設定jre 目錄就可以了。當然,你設定jdk的目錄也是沒有問題的。下面我們演示的是只配置jre目錄 在 tomcat的bin目錄下,找到setclasspath.bat開啟編輯。在 echo off下增加 ...

JDK 執行緒池

在jdk的4種執行緒池之前,先介紹一下執行緒池的幾個引數 固定執行緒池數量,核心執行緒數 最大執行緒數 任務佇列 linkedblockingqueue integer.max value 無界佇列 適用於同時處理固定任務數的場景.public static executorservice newf...