2014-09-22 29 views
2

好吧,我已經問過關於這個問題的一個問題,但需要更多的信息。我會盡可能地與我的問題保持一致。 (因爲我不確定這些概念)。Tomcat中的線程池和請求處理

背景

我有一個java web項目(動態)。我正在寫Restful webservices。下面是我的課

/services 
class Services{ 
static DataSource ds; 
static{ 
ds = createNewDataSource; 
} 

/serviceFirst 
@Consumes(Something) 
@produces(Something) 
public List<Data> doFirst(){ 
    Connection con = ds.getConnection(); 
    ResultSet res = con.execute(preparedStatement); 
    //iterate over res, and create list of Data. 
    return list; 
} 
} 

這是我在這裏說一個非常基本的功能片段。

我有tomcat服務器,我已經部署了這個。我聽說Tomcat有一個大小爲200的線程池(默認情況下)。現在我的問題是,線程池在這裏工作的確切程度。

假設我有兩個請求同時進入。這意味着來自線程池的兩個線程將開始工作。這是否意味着這兩個線程都會有我的班級服務的實例?因爲下面是我如何理解線程和併發。

public class myThread extends Thread(){ 
    public void run(){ 
    //do whatever you wan to do here; 
    } 
} 

在上面,當我打電話對我的線程啓動將執行run()方法的代碼和所有對象,它創建在那裏,將屬於它。

現在,回到Tomcat,有沒有一個run()方法編寫實例化Services類,這就是線程池如何處理200個併發請求。 (顯然,我明白他們需要200個內核才能同時執行,所以忽略它)。

因爲否則,如果tomcat沒有200個不同的線程具有相同的執行路徑(即我的服務類),那麼它將如何處理200個併發請求。

感謝

回答

4

Tomcat的線程池的作品,或多或少,就像你從ExecutorService得到什麼(見Executors)。

YMMV。 Tomcat監聽請求。當它收到一個請求時,它將把這個請求放入一個隊列中。並行地,它維護X個線程,這些線程將不斷嘗試從這個隊列中取出。他們將準備ServletRequestServletResponse對象,以及FilterChain和適當的Servlet來調用。

僞代碼,這看起來像

public void run() { 
    while (true) { 
     socket = queue.take(); 
     ServletRequest request = getRequest(socket.getInputStream()); 
     ServletResponse response = generateResponse(socket.getOutputStream()); 
     Servlet servletInstance = determineServletInstance(request); 
     FilterChain chain = determineFilterChainWithServlet(request, servletInstance); 
     chain.doFilter(request,response); // down the line invokes the servlet#service method 
     // do some cleanup, close streams, etc. 
    } 
} 

確定適當的ServletFilter情況取決於在請求中,你已經配置了網址的映射的URL路徑。對於部署描述符中聲明的每個聲明的<servlet><filter>聲明,Tomcat(和每個Servlet容器)將只管理ServletFilter的單個實例。

因此,每個線程都可能在相同的Servlet實例上執行service(..)方法。

這就是Servlet規範和Servlet API以及Tomcat所保證的。


至於你的Restful網絡服務,read this。它描述了資源如何通常是應用程序範圍的單例,類似於由Servlet容器管理的Servlet實例。也就是說,每個線程都使用同一個實例來處理請求。

+0

所以,如果我弄清楚了。線程池中的每個線程(實際上)都會保存我的Services類的同一個實例。所以,我不需要讓我的DataSource的實例成爲靜態的,(我猜也沒有害處),但即使我保持非靜態,我也可以在聲明和使用它之後實例化它。 – Kraken 2014-09-23 05:20:10

+0

@Kraken這是正確的,但我建議使用正確的控制容器反轉來完成數據源的初始化和注入。 – 2014-09-23 05:36:12