導航:首頁 > 編程語言 > tomcatjava線程

tomcatjava線程

發布時間:2023-04-29 22:51:49

❶ Tomcat篇02-整體架構和I/O模型

本文主要包括tomcat伺服器的目錄結構、工作模式、整體架構、I/O模型以及NIO、NIO2、APR三者的對比介紹。

我們先來看一下核兆tomcat8.5和tomcat9中的home目錄中的文件

可以看到除掉一些說明文件之後,還有7個目錄:

實際上除了主目錄里有lib目錄,在webapps目錄下的web應用中的WEB-INF目錄下也存在一個lib目錄:

兩者的區別在於:

●Tomcat主目錄下的lib目錄:存放的JAR文件 不僅能被Tomcat訪問,還能被所有在Tomcat中發布的java Web應用訪問
●webapps目錄下的Java Web應用的lib目錄:存放的JAR文件 只能被當前Java Web應用訪問

既然有多個lib目錄,那麼肯定就有使用的優先順序,Tomcat類載入器的目錄載入優先順序如下:

Tomcat的類載入器負責為Tomcat本身以及Java Web應用載入相關的類。假如Tomcat的類載入器要為一個Java Web應用載入一個類,類載入器會按照以下優先順序到各個目錄中去查找該類的.class文件,直到找到為止,如果所有目錄中都不存在該類的.class文件,則會拋出異常:

Tomcat不僅可以單獨運行,還可以與其他的Web伺服器集成,作為其他Web伺服器的進程內或進程外的servlet容器。集成的意義在於:對於不支持運行Java Servlet的其他Web伺服器,可通過集成Tomcat來提供運行Servlet的功能。

Tomcat有三種工作模式:

我們先從tomcat的源碼目錄來分析一下tomcat的整體架構,前面我們配置jsvc運行tomcat的時候,我們知道tomcat中啟動運行的最主要的類是 org.apache.catalina.startup.Bootstrap ,那麼我們在tomcat的源碼中的java目錄下的org目錄的apache目錄可以找到主要的源碼的相對應的類。

圖中的目錄如果畫成架構圖,可以這樣表示:

Tomcat 本質上就是一款Servlet 容器,因此 catalina 才是Tomcat的核心 ,其他模塊都是為 catalina 提供支撐的。

單線程阻塞I/O模型是最簡單的一種讓氏慎伺服器I/O模型,單線程即同時只能處理一個客戶端的請求,阻塞即該線程會一直等待,直到處理完成為止。對於多個客戶端訪問,必須要等到前一個客戶端訪問結束才能進行下一個訪問的處理,請求一個一個排隊,只提供一問一答服務。

如上圖所示:這是一個同步阻塞伺服器響應客戶端訪問的時間節點圖。

這種模型的特點在於單線程和阻塞I/O。 單線程即伺服器端只有一個線程處理客戶端的所有請求,客戶端連接與伺服器端的處理線程比是 n:1 ,它無法同時處理多個連接,只能串列處理連接。而阻塞I/O是指伺服器在讀寫數據時是阻塞的,讀取客戶端數據時要等待客戶端發送數據並且把操作系統內核復制到用戶進程中,這時才解除阻塞狀態。寫數據回客戶端時要等待用戶進程將數坦敬據寫入內核並發送到客戶端後才解除阻塞狀態。 這種阻塞帶來了一個問題,伺服器必須要等到客戶端成功接收才能繼續往下處理另外一個客戶端的請求,在此期間線程將無法響應任何客戶端請求。

該模型的特點:它是最簡單的伺服器模型,整個運行過程都只有一個線程,只能支持同時處理一個客戶端的請求(如果有多個客戶端訪問,就必須排隊等待), 伺服器系統資源消耗較小,但並發能力低,容錯能力差。

多線程阻塞I/O模型在單線程阻塞I/O模型的基礎上對其進行改進,加入多線程,提高並發能力,使其能夠同時對多個客戶端進行響應,多線程的核心就是利用多線程機制為每個客戶端分配一個線程。

如上圖所示,伺服器端開始監聽客戶端的訪問,假如有兩個客戶端同時發送請求過來,伺服器端在接收到客戶端請求後分別創建兩個線程對它們進行處理,每條線程負責一個客戶端連接,直到響應完成。 期間兩個線程並發地為各自對應的客戶端處理請求 ,包括讀取客戶端數據、處理客戶端數據、寫數據回客戶端等操作。

這種模型的I/O操作也是阻塞的 ,因為每個線程執行到讀取或寫入操作時都將進入阻塞狀態,直到讀取到客戶端的數據或數據成功寫入客戶端後才解除阻塞狀態。盡管I/O操作阻塞,但這種模式比單線程處理的性能明顯高了,它不用等到第一個請求處理完才處理第二個,而是並發地處理客戶端請求,客戶端連接與伺服器端處理線程的比例是 1:1 。

多線程阻塞I/O模型的特點:支持對多個客戶端並發響應,處理能力得到大幅提高,有較大的並發量,但伺服器系統資源消耗量較大,而且如果線程數過多,多線程之間會產生較大的線程切換成本,同時擁有較復雜的結構。

在探討單線程非阻塞I/O模型前必須要先了解非阻塞情況下套接字事件的檢測機制,因為對於單線程非阻塞模型最重要的事情是檢測哪些連接有感興趣的事件發生。一般會有如下三種檢測方式。

當多個客戶端向伺服器請求時,伺服器端會保存一個套接字連接列表中,應用層線程對套接字列表輪詢嘗試讀取或寫入。如果成功則進行處理,如果失敗則下次繼續。這樣不管有多少個套接字連接,它們都可以被一個線程管理,這很好地利用了阻塞的時間,處理能力得到提升。

但這種模型需要在應用程序中遍歷所有的套接字列表,同時需要處理數據的拼接,連接空閑時可能也會佔用較多CPU資源,不適合實際使用。

這種方式將套接字的遍歷工作交給了操作系統內核,把對套接字遍歷的結果組織成一系列的事件列表並返回應用層處理。對於應用層,它們需要處理的對象就是這些事件,這是一種事件驅動的非阻塞方式。

伺服器端有多個客戶端連接,應用層向內核請求讀寫事件列表。內核遍歷所有套接字並生成對應的可讀列表readList和可寫列表writeList。readList和writeList則標明了每個套接字是否可讀/可寫。應用層遍歷讀寫事件列表readList和writeList,做相應的讀寫操作。

內核遍歷套接字時已經不用在應用層對所有套接字進行遍歷,將遍歷工作下移到內核層,這種方式有助於提高檢測效率。 然而,它需要將所有連接的可讀事件列表和可寫事件列表傳到應用層,假如套接字連接數量變大,列表從內核復制到應用層也是不小的開銷。 另外,當活躍連接較少時, 內核與應用層之間存在很多無效的數據副本 ,因為它將活躍和不活躍的連接狀態都復制到應用層中。

通過遍歷的方式檢測套接字是否可讀可寫是一種效率比較低的方式,不管是在應用層中遍歷還是在內核中遍歷。所以需要另外一種機制來優化遍歷的方式,那就是 回調函數 。內核中的套接字都對應一個回調函數,當客戶端往套接字發送數據時,內核從網卡接收數據後就會調用回調函數,在回調函數中維護事件列表,應用層獲取此事件列表即可得到所有感興趣的事件。

內核基於回調的事件檢測方式有兩種

第一種是用 可讀列表readList 和 可寫列表writeList 標記讀寫事件, 套接字的數量與 readList 和 writeList 兩個列表的長度一樣

上面兩種方式由操作系統內核維護客戶端的所有連接並通過回調函數不斷更新事件列表,而應用層線程只要遍歷這些事件列表即可知道可讀取或可寫入的連接,進而對這些連接進行讀寫操作,極大提高了檢測效率,自然處理能力也更強。

單線程非阻塞I/O模型最重要的一個特點是,在調用讀取或寫入介面後立即返回,而不會進入阻塞狀態。雖然只有一個線程,但是它通過把非阻塞讀寫操作與上面幾種檢測機制配合就可以實現對多個連接的及時處理,而不會因為某個連接的阻塞操作導致其他連接無法處理。在客戶端連接大多數都保持活躍的情況下,這個線程會一直循環處理這些連接,它很好地利用了阻塞的時間,大大提高了這個線程的執行效率。

單線程非阻塞I/O模型的主要優勢體現在對多個連接的管理,一般在同時需要處理多個連接的發場景中會使用非阻塞NIO模式,此模型下只通過一個線程去維護和處理連接,這樣大大提高了機器的效率。一般伺服器端才會使用NIO模式,而對於客戶端,出於方便及習慣,可使用阻塞模式的套接字進行通信。

在多核的機器上可以通過多線程繼續提高機器效率。最朴實、最自然的做法就是將客戶端連接按組分配給若干線程,每個線程負責處理對應組內的連接。比如有4個客戶端訪問伺服器,伺服器將套接字1和套接字2交由線程1管理,而線程2則管理套接字3和套接字4,通過事件檢測及非阻塞讀寫就可以讓每個線程都能高效處理。

多線程非阻塞I/O模式讓伺服器端處理能力得到很大提高,它充分利用機器的CPU,適合用於處理高並發的場景,但它也讓程序更復雜,更容易出現問題(死鎖、數據不一致等經典並發問題)。

最經典的多線程非阻塞I/O模型方式是Reactor模式。首先看單線程下的Reactor,Reactor將伺服器端的整個處理過程分成若干個事件,例如分為接收事件、讀事件、寫事件、執行事件等。Reactor通過事件檢測機制將這些事件分發給不同處理器去處理。在整個過程中只要有待處理的事件存在,即可以讓Reactor線程不斷往下執行,而不會阻塞在某處,所以處理效率很高。

基於單線程Reactor模型,根據實際使用場景,把它改進成多線程模式。常見的有兩種方式:一種是在耗時的process處理器中引入多線程,如使用線程池;另一種是直接使用多個Reactor實例,每個Reactor實例對應一個線程。

Reactor模式的一種改進方式如下圖所示。其整體結構基本上與單線程的Reactor類似,只是引入了一個線程池。由於對連接的接收、對數據的讀取和對數據的寫入等操作基本上都耗時較少,因此把它們都放到Reactor線程中處理。然而,對於邏輯處理可能比較耗時的工作,可以在process處理器中引入線程池,process處理器自己不執行任務,而是交給線程池,從而在Reactor線程中避免了耗時的操作。將耗時的操作轉移到線程池中後,盡管Reactor只有一個線程,它也能保證Reactor的高效。

Reactor模式的另一種改進方式如下圖所示。其中有多個Reactor實例,每個Reactor實例對應一個線程。因為接收事件是相對於伺服器端而言的,所以客戶端的連接接收工作統一由一個accept處理器負責,accept處理器會將接收的客戶端連接均勻分配給所有Reactor實例,每個Reactor實例負責處理分配到該Reactor上的客戶端連接,包括連接的讀數據、寫數據和邏輯處理。這就是多Reactor實例的原理。

Tomcat支持的I/O模型如下表(自8.5/9.0 版本起,Tomcat移除了對BIO的支持),在 8.0 之前 , Tomcat 默認採用的I/O方式為 BIO , 之後改為 NIO。 無論 NIO、NIO2 還是 APR, 在性能方面均優於以往的BIO。

Tomcat中的NIO模型是使用的JAVA的NIO類庫,其內部的IO實現是同步的(也就是在用戶態和內核態之間的數據交換上是同步機制),採用基於selector實現的非同步事件驅動機制(這里的非同步指的是selector這個實現模型是使用的非同步機制)。 而對於Java來說,非阻塞I/O的實現完全是基於操作系統內核的非阻塞I/O,它將操作系統的非阻塞I/O的差異屏蔽並提供統一的API,讓我們不必關心操作系統。JDK會幫我們選擇非阻塞I/O的實現方式。

NIO2和前者相比的最大不同就在於引入了非同步通道來實現非同步IO操作,因此也叫AIO(Asynchronous I/O)。NIO.2 的非同步通道 APIs 提供方便的、平台獨立的執行非同步操作的標准方法。這使得應用程序開發人員能夠以更清晰的方式來編寫程序,而不必定義自己的 Java 線程,此外,還可通過使用底層 OS 所支持的非同步功能來提高性能。如同其他 Java API 一樣,API 可利用的 OS 自有非同步功能的數量取決於其對該平台的支持程度。

非同步通道提供支持連接、讀取、以及寫入之類非鎖定操作的連接,並提供對已啟動操作的控制機制。Java 7 中用於 Java Platform(NIO.2)的 More New I/O APIs,通過在 java.nio.channels 包中增加四個非同步通道類,從而增強了 Java 1.4 中的 New I/O APIs(NIO),這些類在風格上與 NIO 通道 API 很相似。他們共享相同的方法與參數結構體,並且大多數對於 NIO 通道類可用的參數,對於新的非同步版本仍然可用。主要區別在於新通道可使一些操作非同步執行。

非同步通道 API 提供兩種對已啟動非同步操作的監測與控制機制。第一種是通過返回一個 java.util.concurrent.Future 對象來實現,它將會建模一個掛起操作,並可用於查詢其狀態以及獲取結果。第二種是通過傳遞給操作一個新類的對象, java.nio.channels.CompletionHandler ,來完成,它會定義在操作完畢後所執行的處理程序方法。每個非同步通道類為每個操作定義 API 副本,這樣可採用任一機制。

Apache可移植運行時(Apache Portable Runtime,APR) 是Apache HTTP伺服器的支持庫,最初,APR是作為Apache HTTP伺服器的一部分而存在的,後來成為一個單獨的項目。其他的應用程序可以使用APR來實現平台無關性(跨平台)。APR提供了一組映射到下層操作系統的API,如果操作系統不支持某個特定的功能,APR將提供一個模擬的實現。這樣程序員使用APR編寫真正可在不同平台上移植的程序。

順利安裝完成後會顯示apr的lib庫路徑,一般都是 /usr/local/apr/lib

安裝完成之後我們還需要修改環境變數和配置參數

這里我們使用的是systemd調用jsvc來啟動tomcat,所以我們直接在systemd對應的tomcat的unit文件中的 ExecStart 中添加一個路徑參數 -Djava.library.path=/usr/local/apr/lib 指向apr庫的路徑:

然後我們在tomcat的home目錄下的conf子目錄中對server.xml文件進行修改

把8080埠對應的配置修改成apr:(其他埠配置也類似)

重啟tomcat服務我們從tomcat的日誌中就可以看到協議已經從默認的NIO變成了apr。

NIO性能是最差的這是毋庸置疑的,如果是考慮到高並發的情況,顯然非同步非阻塞I/O模式的NIO2和APR庫在性能上更有優勢,實際上NIO2的性能表現也和APR不相上下,但是NIO2要求Tomcat的版本要在8.0以上,而APR只需要5.5以上即可,但是APR需要額外配置庫環境,相對於內置集成的NIO2來說APR這個操作比較麻煩,兩者各有優劣。具體使用哪個還是需要結合實際業務需求和環境進行測試才能決定。

❷ 請問在java中,多個客戶端同時訪問同一個WEB資源, tomcat是怎麼處理的

內部是用多線程處理的。單個線程內部的資源都是相互獨立的。
不是每一個請求一個線程,應該是每個客戶端一條或一組線程

❸ 如何用java程序控制Tomcat重啟

因為平時Tomcat在windows上的重啟一般都是用vbs或者是 .bat腳本來寫的.只要做能做到用JAVA調用這兩種 腳本就可以了. 在JAVA的API裡面.可以用代碼控制本地的可執行文件 而不能直接調用腳本.因此需要把腳本轉 換成可執行文件可以下載 visualVBS來把vbs腳本轉換成.exe .bat轉換的腳本更多.網上搜索一下就能找到了. 之後在線程裡面直接調用JAVA API裡面的執行代碼就可以 做到重啟TOMCAT了.DEMO: 首先是重啟腳本,寫成.vbs set WshShell=WScript.CreateObject("WScript.Shell") WshShell.Run("net stop tomcat5") WScript.Sleep(10000) WshShell.Run("net start tomcat5") 然後用visualVBS轉換成.exe文件 然後做一個類,重啟Tomcat專用 package com.uf.tool.util; public class TomcatReset { private String tomcat=""; public TomcatReset() {Configconfig=Config.getConfig(); tomcat=config.getProperties("tomcat");} public void tomcatRun(){try{ System.out.println("the command is:"+tomcat); Process child = Runtime.getRuntime().exec(tomcat); } catch

❹ 如何用java程序啟動和關閉Tomcat

package d2008;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;

public class ControlTomcat {

/**
* @param args
*/
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
Process process = Runtime.getRuntime().exec("cmd.exe /c D:\\apache-tomcat-6.0.18\\bin\\startup.bat"); // 調用外部程序
final InputStream in = process.getInputStream();
BufferedReader br=new BufferedReader(new InputStreamReader(in));
StringBuilder buf = new StringBuilder();
String line = null;
while((line = br.readLine()) != null) buf.append(line);
System.out.println("滾茄讓納悔輸出結果為:" + buf);

// new Thread(new Runnable() {
// public void run() {
// BufferedReader br = new BufferedReader(new InputStreamReader(in));
// try {
// while(br.readLine() != null) ;
// } catch (IOException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// }
// }).start();// 啟動單獨的線程來清空process.getInputStream()的緩沖區
// InputStream error = process.getErrorStream();
// BufferedReader br = new BufferedReader(new InputStreamReader(error));
// StringBuilder buf = new StringBuilder(); // 保存輸出結果流
// String line = null;
// while((line = br.readLine()) != null) buf.append(line); // 循環等待ffmpeg進程結束
// System.out.println("輸出結果為:" + buf);
}

}
關鍵是exe參數命令cmd.exe /c D:\\apache-tomcat-6.0.18\\bin\\startup.bat
如果要停止cmd.exe /c D:\大局\apache-tomcat-6.0.18\\bin\\shutdown.bat

❺ maven 命令啟動javaweb項目如何設置tomcat最大連接數,線程數等。【求解】

修改搏櫻 server.xml 的maxThread,mvn tomcat:run -Dmaven.tomcat.maxThread=xxx不知道好不山銀鍵好逗巧使

❻ java的服務是每收到一個請求就新開一個線程來處理嗎tomcat

java的多線程處理是根據實際的業務情況提供飢帶固定數量的線程池的,如果任何請求都新開一個線程的話,那麼再大,再好的伺服器也無法承受爛羨蘆,正確的做法是:

  1. 建立線程池機制,預先分配好固定大小的線派弊程數量

  2. 系統受到請求後從線程池中取出空閑線程

  3. 當無空閑線程時,請求為等待狀態,直到有空閑線程進行處理

❼ java的服務是每收到一個請求就新開一個線程來處理嗎tomcat

不是...
基本上是每一個會話一個線程處理,線程會等待一定的時間,如果沒有上下文,那麼這個線程就結束了..如果有請求,就歷春刷新等待時間.
一個會話就是一個終端從從一個地方連續發來的若干次請求... 通常前台會生成一個類似uuid的東西,在後台保存,當瀏覽器關閉陸爛察之後,這個標記值就消失了..當你早茄再次打開瀏覽器的時候,這個值又會重新生成..
後台會根據這個值,開啟一個線程等待處理...

❽ java開發中單tomcat能支持多少並發不同操作系統一樣么

Tomcat 默認是 150,也就是說同時支持 150 個並發,當然了,也可以將其改大,理論是想多大就多大。
具體能承載多少並發,需要看硬體的配置,CPU 越多性能越高,分配給 JVM 的內存越多性能也就越高,但也會加重 GC 的負擔。
當某個應用擁有 250 個鬧神蠢以上並發的時候,應考慮瞎氏應用伺服器的集群。
並發和同時在線用戶數是不一樣的,因為不同的用戶操作是有間隔的。如果邏輯復雜,請求執行時間過長,就會佔用過多的性能,導致同時在線用戶數下降,但是對並發沒有影響。
操作系統對於進程中的線程數有一定的限制:
Windows 每液陪個進程中的線程數不允許超過 2000;
Linux 每個進程中的線程數不允許超過 1000;

另外,在 Java 中每開啟一個線程需要耗用 1MB 的 JVM 內存空間用於作為線程棧之用。

❾ java,tomcat,CPU使用率高,應用程序卡死

先從進程里去確認是哪個進程佔用CPU高
如果確認是tomcat,再去查看你給的最大堆戚世值是多少
再用工具去確認在高CPU時java的內存占高腔肢用和使用情圓早況
再去確認線程情況
多種情況結合再定位問題所在

❿ tomcat服務由於java進程沒有關閉無法停止。只能終止服務才能完全關閉的問題

一般拆尺這種情況是,程序里啟動了自定義線程或線程池,而tomcat關閉時,沒有關閉這個線程或線程池。造成tomcat停止不了造銷培成虧御唯的

閱讀全文

與tomcatjava線程相關的資料

熱點內容
更新後版本英文怎麼說 瀏覽:267
桌面雲配置文件分離 瀏覽:505
iphone5如何升級4g網路 瀏覽:5
團購是在哪個app 瀏覽:897
打開多個word文檔圖片就不能顯示 瀏覽:855
騰訊新聞怎麼切換版本 瀏覽:269
app安裝失敗用不了 瀏覽:326
桌面文件滑鼠點開會變大變小 瀏覽:536
手機誤刪系統文件開不了機 瀏覽:883
微信兔子甩耳朵 瀏覽:998
android藍牙傳文件在哪裡 瀏覽:354
蘋果6s軟解是真的嗎 瀏覽:310
c語言代碼量大 瀏覽:874
最新網路衛星導航如何使用 瀏覽:425
以下哪些文件屬於圖像文件 瀏覽:774
zycommentjs 瀏覽:414
確認全血細胞減少看哪些數據 瀏覽:265
文件有哪些要求 瀏覽:484
cad打開時會出現兩個文件 瀏覽:65
什麼是轉基因網站 瀏覽:48

友情鏈接