1. 程式人生 > >Tomcat中的執行緒池原理(APR和ThreadPool)

Tomcat中的執行緒池原理(APR和ThreadPool)

一、容器簡化了程式設計師自身的多執行緒程式設計。

        各種Web容器,如Tomcat,Resion,Jetty等都有自己的執行緒池(可在配置檔案中配置),所以在客戶端進行請求呼叫的時候,程式設計師不用針對Client的每一次請求,都新建一個執行緒。而容器會自動分配執行緒池中的執行緒,提高訪問速度。

二、Tomcat執行緒池實現:

1、使用APR的Pool技術,使用了JNI。

Tomcat從5.5.17開始,為了提高響應速度和效率,使用了Apache Portable Runtime(APR)作為最底層,使用了APR中包含Socket、緩衝池等多種技術,效能也提高了。APR也是Apache HTTPD的最底層。

2、使用Java實現的Thread Pool。

      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進行埠轉發,讓兩個埠去分擔一個埠的執行緒排程,就有可能減少執行緒排程的併發,從而提高處理能力,減少資源消耗。

三、配置Tomcat執行緒池以使用高併發連線

1.開啟共享的執行緒池:

<Service name="Catalina">  
  <!--The connectors can use a shared executor, you can define one or more named thread pools-->  
  
    <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"    
    maxThreads="1000" minSpareThreads="50" maxIdleTime="600000"/>

預設前後是註釋<!-- -->掉的,去掉就可以了。

重要引數說明:

name:共享執行緒池的名字。這是Connector為了共享執行緒池要引用的名字,該名字必須唯一。預設值:None;

namePrefix:在JVM上,每個執行執行緒都可以有一個name 字串。這一屬性為執行緒池中每個執行緒的name字串設定了一個字首,Tomcat將把執行緒號追加到這一字首的後面。預設值:tomcat-exec-;

maxThreads:該執行緒池可以容納的最大執行緒數。預設值:200;

maxIdleTime:在Tomcat關閉一個空閒執行緒之前,允許空閒執行緒持續的時間(以毫秒為單位)。只有當前活躍的執行緒數大於minSpareThread的值,才會關閉空閒執行緒。預設值:60000(一分鐘)。

minSpareThreads:Tomcat應該始終開啟的最小不活躍執行緒數。預設值:25。

threadPriority:執行緒的等級。預設是Thread.NORM_PRIORITY

2. 在Connector中指定使用共享執行緒池:

<Connector executor="tomcatThreadPool"
           port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" 
           minProcessors="5"
           maxProcessors="75"
           acceptCount="1000"/>

重要引數說明:
executor:表示使用該引數值對應的執行緒池;

minProcessors:伺服器啟動時建立的處理請求的執行緒數;

maxProcessors:最大可以建立的處理請求的執行緒數;

acceptCount:指定當所有可以使用的處理請求的執行緒數都被使用時,可以放到處理佇列中的請求數,超過這個數的請求將不予處理。

BTW:我測試了一下,由於每次請求不再需要重新分配執行緒,系統響應速度還是有很明顯的改善的。

相關推薦

Tomcat執行原理APRThreadPool

一、容器簡化了程式設計師自身的多執行緒程式設計。         各種Web容器,如Tomcat,Resion,Jetty等都有自己的執行緒池(可在配置檔案中配置),所以在客戶端進行請求呼叫的時候,程式設計師不用針對Client的每一次請求,都新建一個執行緒。而容器會自

java執行原理入門版——看完還不懂我直播吃香

網上關於java執行緒池的部落格,大多是直接分析ThreadPoolExecutor類的實現,但是他們就像是做中文翻譯一樣,但是很少有講到本質的東西。 這篇部落格從根本出發,看完可以自己實現一個簡單執行緒池。下面正式開始。 一、我們知道,用java建立一條新執行

執行原理執行的使用

這篇文章通過介紹執行緒池的常見用法,總結前面學習到的內容。 主要包括 ThreadPoolExecutor的使用 ScheduledThreadPoolExecutor的使用 ExecutorCompletionService的使用 1. 統計某個區間

執行原理:ScheduledThreadPoolExecutor

ScheduledThreadPoolExecutor用於定時任務,這裡的定時意義在於: 指定延時後執行任務。 週期性重複執行任務。 我們接著分析ScheduledThreadPoolExecutor原始碼,從類宣告開始 類宣告 public c

JDK併發之:執行自定義ThreadFactory

ThreadPoolExecutor的建構函式中,執行緒的生成有ThreadFactory生成,建構函式中的ThreadFactory預設為Eexecutors.defaultThreadFactory()。自定義ThreadFactory可以根治執行緒池究竟何時建立了多少執

Java 執行ThreadPoolExecutor基於jdk1.8

介紹 執行緒池的作用就是提供一種對執行緒的管理,避免由於過多的建立和銷燬執行緒所造成的開銷。在一個“池”中維護著一定數量的執行緒,達到可重複利用的效果。在Java中,執行緒池的實現主要是通過Threa

Java 執行ThreadPoolExecutor基於jdk1.8

private boolean addWorker(Runnable firstTask, boolean core) 首先分析一下引數,firstTask就是指我們使用者傳入的需要執行的認為,

建立執行那麼容易,為什麼非要讓我使用執行深深深入剖析

一、概述 1、問題 先看我們遇到的問題:我們建立執行緒的方式很簡單,new Thread(() -> {...}),就是因為這麼簡單粗暴的方式,才帶來了致命的問題。首先執行緒的建立和銷燬都是很耗時很浪費效能的操作,你用執行緒為了什麼?為了就是非同步,為了就是提升效能。簡單的new三五個Thread還好,

執行間機制同步互斥

執行緒間機制 { 多執行緒共享同一個程序子地址空間 優點: 執行緒間很容易進行通訊 1、 通過全域性變數實現資料共享和交換 缺點: 多個執行緒同時訪問共享物件時需要引入同步和互斥機制 }

Handler多執行通訊例子postsendMessage

前言   Android的訊息傳遞機制是另外一種形式的“事件處理”,這種機制主要是為了解決Android應用中多執行緒的問題,在Android中不允許Activity新啟動的執行緒訪問該Activity裡的UI元件,這樣會導致新啟動的執行緒無法改變UI元件的屬性值。但實際開發中,很多地方需要在

執行的通訊waitnotify

執行緒通訊 執行緒通訊即一個執行緒完成了自己的任務時,通知另外一個執行緒去完成另外一個任務。 wait():  等待   如果執行緒執行了wait方法,那麼該執行緒會進入等待的狀態,等待狀態下的執行緒必須要被其他執行緒呼叫notify方法才能喚醒。 notify():

java併發程式設計一一執行原理分析

合理的設定執行緒池的大小 接著上一篇探討執行緒留下的尾巴。如果合理的設定執行緒池的大小。 要想合理的配置執行緒池的大小、首先得分析任務的特性,可以從以下幾個角度分析: 1、任務的性質:CPU密集型任務、IO密集型任務、混合型任務等; 2、任務的優先順序:高、中、低; 3、任務的執行時

Java執行ThreadPoolExecutor原理探究

一、 前言 執行緒池主要解決兩個問題:一方面當執行大量非同步任務時候執行緒池能夠提供較好的效能,,這是因為使用執行緒池可以使每個任務的呼叫開銷減少(因為執行緒池執行緒是可以複用的)。另一方面執行緒池提供了一種資源限制和管理的手段,比如當執行一系列任務時候對執行緒的管理,每個ThreadPool

深入理解Java執行原理分析與使用尤其當執行佇列滿了之後事項

在這裡借花獻佛了,那別人的東西學一學了。在我們的開發中“池”的概念並不罕見,有資料庫連線池、執行緒池、物件池、常量池等等。下面我們主要針對執行緒池來一步一步揭開執行緒池的面紗。使用執行緒池的好處1、降低資源消耗可以重複利用已建立的執行緒降低執行緒建立和銷燬造成的消耗。2、提高響應速度當任務到達時,任務可以不需

Java高併發程式設計十一:Java執行

在開發過程中,合理地使用執行緒池能夠帶來3個好處。 降低資源消耗。通過重複利用已建立的執行緒降低執行緒建立和銷燬造成的消耗。 提高響應速度。當任務到達時,任務可以不需要等到執行緒建立就能立即執行。 提高執行緒的可管理性。執行緒是稀缺資源,如果無限制地建立

[C++][執行][完整實現] 轉:執行原理及建立C++實現

文章的主要框架是參考這篇文件的,http://jacky-dai.iteye.com/blog/1090285, 關於作者  張中慶,西安交通大學軟體所,在讀碩士,目前研究方向為分散式網路與移動中介軟體,對Linux極其愛好,可以通過[email protecte

併發2--java執行原理

    執行緒池Execotors工具可以建立普通的執行緒池以及schedule排程任務的排程池。使用執行緒池的一個優點就是:     1、執行緒是稀缺資源,使用執行緒池可以減少建立和銷燬執行緒的次數

Tomcat執行配置Tomcat6

1、執行緒池配置(Tomcat6下) 使用執行緒池,用較少的執行緒處理較多的訪問,可以提高tomcat處理請求的能力。使用方式: 首先。開啟/conf/server.xml,增加 <Executor name="tomcatThreadPool" namePrefi

Java併發包執行ThreadPoolExecutor原理探究

一、執行緒池簡介   執行緒池的使用主要是解決兩個問題:①當執行大量非同步任務的時候執行緒池能夠提供更好的效能,在不使用執行緒池時候,每當需要執行非同步任務的時候直接new一個執行緒來執行的話,執行緒的建立和銷燬都是需要開銷的。而執行緒池中的執行緒是可複用的,不需要每次執行非同步任務的時候重新建立和銷燬執行

沉澱再出發:java執行解析

沉澱再出發:java中執行緒池解析 一、前言    在多執行緒執行的環境之中,如果執行緒執行的時間短但是啟動的執行緒又非常多,執行緒運轉的時間基本上浪費在了建立和銷燬上面,因此有沒有一種方式能夠讓一個執行緒執行完自己的任務之後又被重複使用呢?執行緒池的出現就是為了解決這個問題。到了現在