2010-05-06 76 views
2

我開發了一個使用運行servlet的Tomcat的簡單服務器。Servlet似乎並沒有以線程的方式執行

該servlet調用命令行程序 - 執行大約20秒鐘,然後通過JSON將結果返回給用戶。問題是 - 如果我做出2個以上的同時請求,那麼這個servlet將阻塞,直到前面的一個請求完成。

一個例子可以在下面看到 - 「Im in」是servlet的頂部,結果列表是在servlet執行之後。所有請求都是在同一時間完成的 - 但您可以清楚地看到它們不會被同時處理。我需要在tomcat中更改哪些設置才能同時處理所有請求?

 
Im in 

Im in 

FVFNT01 STOP_IDLE FVFNT03 STOP_IDLE FVFNT16 STOP_IDLE FVFNT17 STOP_IDLE 
FVFNT01 STOP_IDLE FVFNT03 STOP_IDLE FVFNT16 STOP_IDLE FVFNT17 STOP_IDLE 
Im in 

FVFNT01 STOP_IDLE FVFNT03 STOP_IDLE FVFNT16 STOP_IDLE FVFNT17 STOP_IDLE 
Im in 

FVFNT01 STOP_IDLE FVFNT03 STOP_IDLE FVFNT16 STOP_IDLE FVFNT17 STOP_IDLE 
Im in 

FVFNT01 STOP_IDLE FVFNT03 STOP_IDLE FVFNT16 STOP_IDLE FVFNT17 STOP_IDLE 
Im in 

FVFNT01 STOP_IDLE FVFNT03 STOP_IDLE FVFNT16 STOP_IDLE FVFNT17 STOP_IDLE 
Im in 

FVFNT01 STOP_IDLE FVFNT03 STOP_IDLE FVFNT16 STOP_IDLE FVFNT17 STOP_IDLE 
Im in 

FVFNT01 STOP_IDLE FVFNT03 STOP_IDLE FVFNT16 STOP_IDLE FVFNT17 STOP_IDLE 
+0

我不明白你的輸出。嘗試添加線程名稱,以便您可以看到哪些線程處理您的請求。您可以通過調用Thread.currentThread()。getName()來獲取當前線程名稱。另外,試着將你的「Im in」消息與結果「聯​​系起來」,即記住操作的開始時間並將結果寫入(原子計數器會更好)。 – 2010-05-06 10:20:53

回答

1

默認情況下,同時處理對servlet的請求。沒有設置啓用/禁用此行爲。這是由JavaDoc for HttpServlet證實:

的Servlet通常在 多線程的服務器上運行,所以要知道 一個Servlet必須處理的併發請求 並小心地同步 訪問共享資源。

但是,如果您的servlet實現了標記接口SingleThreadModel,則該servlet一次只能處理一個請求。但是,使用這個接口通常被認爲是不好的做法,因爲你沒有提到它,所以我假設你沒有使用它。

當然,即使你沒有實現SingleThreadModel,你也可以使用(可能是不適當的)同步來使任何servlet單線程化。

class MyServlet extends HttpServlet { 

    private void Object sharedObject = new Object() 

    protected synchronized void doGet(HttpServletRequest req, HttpServletResponse resp) { 
    // method logic goes here 
    } 

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) { 

    synchronized(sharedObject) { 
     // method logic goes here 
    } 

    } 

    protected void doPut(HttpServletRequest req, HttpServletResponse resp) { 

    synchronized(this) { 
     // method logic goes here 
    } 
    } 
} 

在上面的例子中,只有一個線程可在-A-時間爲一個線程來執行doPost()執行相同的請求的方法,儘管它是可能的(例如),而另一個正在執行doGet()

如果您不明白爲什麼會這樣,那麼我建議您在進一步調查問題之前,先閱讀Java中的併發編程。

+0

我沒有提到我的代碼中的SingleThreadModel - 它擴展了HttpServlet – RenegadeAndy 2010-05-06 09:46:01

+0

然後它已經是一個多線程servlet – 2010-05-06 09:50:57

+0

然後它必須是我的實現在我打電話的每個獲取請求的開始: System.out.println(「算我一個 」); \t運行時rt = Runtime.getRuntime(); 過程PR = rt.exec( ,其上運行的程序,然後返回輸出 - 但那我認爲其阻塞....位=給出的輸出:IM在 FVFNT01 STOP_IDLE FVFNT03 STOP_IDLE FVFNT16 STOP_IDLE FVFNT17 STOP_IDLE 林在 FVFNT01 STOP_IDLE FVFNT03 STOP_IDLE FVFNT16 STOP_IDLE FVFNT17 STOP_IDLE 林在 FVFNT01 STOP_IDLE FVFNT03 STOP_IDLE FVFNT16 STOP_IDLE FVFNT17 STOP_IDLE 林在 FVFNT01 STOP_IDLE FVFNT03 STOP_IDLE FVFNT16 STOP_IDLE FV – RenegadeAndy 2010-05-06 10:02:59

0

確保您的請求使用不同的HTTP連接,並檢查您的tomcat配置,如果它允許多個線程(默認情況下它會這樣做,所以除非您已更改它,否則應該可以)。

+0

當你說不同的連接 - 來自localhost的10個請求 - localhost不會滿足這個嗎? – RenegadeAndy 2010-05-06 10:39:27

+0

本地主機是好的,但通過1個連接發送10個請求或通過10個連接發送10個請求是有區別的。如果所有請求都是通過單個連接傳送的,則它們將按順序處理。 – 2010-05-06 11:15:16

1

問題出在您的測試客戶端。它正在同步觸發請求。它應該異步觸發請求,然後servlet將能夠做同樣的事情:)

大約4天前問過同樣的問題,我已經發布了一個代碼示例的答案,測試客戶端應如何看起來像: Servlet requests are executed sequentially for no apparent reason in Glassfish v3。你也可能會覺得它很有用。

+0

我的測試客戶端是我的網絡瀏覽器......您是否建議測試來自不同主機的觸發請求是一個答案? – RenegadeAndy 2010-05-06 12:17:15

+0

不,在不同線程(異步)觸發請求是答案。你(基本上是webbrowser)在單線程(同步)中觸發所有請求。我必須在這裏複製鏈接的答案,以便您閱讀它嗎? :) – BalusC 2010-05-06 12:23:41

+0

哈哈沒有生病去讀它 – RenegadeAndy 2010-05-06 12:31:26

0

一旦你將運行你的應用程序在Tomcat(而不是通過eclipse在調試模式),相同的服務器的相同請求將被線程化。

一個簡單的測試用例可以做: 作一些簡單的doGet它會做的下一件事:

PrintWriter printWriter = response.getWriter(); 
printWriter.append("doGet: Hello from testServlet! doing some thread check :)"); 
try{Thread.sleep(15*1000);}catch(Exception e){} 
printWriter.close(); 

現在運行Web瀏覽器,並多次運行這個servlet,你會看到,他們都同時返回(+ - )。 如果servlet沒有線程化,你會期望第一個將在15秒後返回,第二個在30秒之後等等......

相關問題