轉:Tomcat執行緒池apr和threadPool

luckyfriends發表於2013-02-21

轉:Tomcat執行緒池apr和threadPool

Tomcat是使用最廣的Java Web容器,功能強大,可擴充套件性強。最新版本的Tomcat(5.5.17)為了提高響應速度和效率,使用了(APR)作為最底層,使用了APR中包含Socket、緩衝池等多種技術,效能也提高了。APR也是Apache HTTPD的最底層。可想而知,同屬於(Apache Software Foundation)中的成員,互補互用的情況還是很多的,雖然使用了不同的開發語言。

Tomcat 的執行緒池位於tomcat-util.jar檔案中,包含了兩種執行緒池方案。

方案一:使用APR的Pool技術,使用了JNI;

方案二:使用Java實現的ThreadPool。這裡介紹的是第二種。如果想了解APR的Pool技術,可以檢視APR的原始碼。

ThreadPool預設建立了5個執行緒,儲存在一個200維的執行緒陣列中,建立時就啟動了這些執行緒,當然在沒有請求時,它們都處理“等待”狀態(其實就是一個while迴圈,不停的等待notify)。如果有請求時,空閒執行緒會被喚醒執行使用者的請求。

具體的請求過程是:服務啟動時,建立一個一維執行緒陣列(maxThread=200個),並建立空閒執行緒(minSpareThreads=5個)隨時等待使用者請求。當有使用者請求時,呼叫 threadpool.runIt(ThreadPoolRunnable)方法,將一個需要執行的例項傳給ThreadPool中。其中使用者需要執行的例項必須實現ThreadPoolRunnable介面。 ThreadPool 首先查詢空閒的執行緒,如果有則用它執行要執行ThreadPoolRunnable;如果沒有空閒執行緒並且沒有超過maxThreads,就一次性建立 minSpareThreads個空閒執行緒;如果已經超過了maxThreads了,就等待空閒執行緒了。總之,要找到空閒的執行緒,以便用它執行例項。找到後,將該執行緒從執行緒陣列中移走。 接著喚醒已經找到的空閒執行緒,用它執行執行例項(ThreadPoolRunnable)。執行完ThreadPoolRunnable後,就將該執行緒重新放到執行緒陣列中,作為空閒執行緒供後續使用。

由此可以看出,Tomcat的執行緒池實現是比較簡單的,ThreadPool.java也只有840行程式碼。用一個一維陣列儲存空閒的執行緒,每次以一個較小步伐(5個)建立空閒執行緒並放到執行緒池中。使用時從陣列中移走空閒的執行緒,用完後,再“歸還”給執行緒池

tomcat5.5.10以上版本支援apr,支援透過apache runtime module進行JNI呼叫,使用原生程式碼來加速網路處理。

如果不使用apr之前,Tomcat的Servlet執行緒池使用的是阻塞IO的模式,使用apr之後,執行緒池變成了 NIO的非阻塞模式,而且這種NIO還是使用了作業系統的原生程式碼,看tomcat文件上面的說法是,極大提升web處理能力,不再需要專門放一個web server處理靜態頁面了。 
我自己直觀的感受是,不用apr之前,你配置多少個等待執行緒,tomcat就會啟動多少個執行緒掛起等待,使用apr以後,不管你配置多少,就只有幾個NIO排程的執行緒,這一點你可以透過kill -3 PID,然後察看log得知。

假設不使用apr,可能埠的執行緒排程能力比較差,所以透過iptables進行埠轉發,讓兩個埠去分擔一個埠的執行緒排程,就有可能減少執行緒排程的併發,從而提高處理能力,減少資源消耗。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/14710393/viewspace-754443/,如需轉載,請註明出處,否則將追究法律責任。

相關文章