2017-04-20 91 views
1

這看起來像我打破了我的想法。我已經在Java 9上用Tomcat 9(與8相同)創建了一個新項目(同樣是8)。它只有一個servlet的Tomcat執行服務同步

@WebServlet(urlPatterns = "/*") 
public class Servlet extends HttpServlet { 

    @Override 
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
     System.out.println(new Date().getTime() /1000 + " " + Thread.currentThread().getName() + " Start"); 
     /*long i = 0; 

     while (i < 3000000000L) { 
      if (i % 2 == 0) { 
       i++; 
      } else { 
       i++; 
      } 
     }*/ 
     try { 
      Thread.sleep(2000); 
     } catch (Exception e) { 
      throw new RuntimeException(e); 
     } 
     System.out.println(new Date().getTime()/1000 + " " + Thread.currentThread().getName() + " Done"); 
    } 
} 

我所有的經驗,說我對這種方法以異步方式工作,但我所說的,通過3個標籤的servlet在我的瀏覽器(同時爲可能的),我看到這樣的畫面在我的日誌:

1492723549 http-nio-9999-exec-2 Start 
1492723551 http-nio-9999-exec-2 Done 
1492723551 http-nio-9999-exec-1 Start 
1492723553 http-nio-9999-exec-1 Done 
1492723553 http-nio-9999-exec-3 Start 
1492723555 http-nio-9999-exec-3 Done 

可以看出,每個請求都會鎖定方法,直到它完成。有人能告訴我爲什麼嗎?我真的期望3個同時開始和2秒後3個完成。

謝謝!

+0

爲什麼你有一個'Thread.sleep(2000);'?你正在使用非阻塞的io,而你正在阻止。 –

+0

我想阻止一個線程來模擬一些辛苦的工作。池中的其他線程是免費的。不是嗎? –

+0

不要阻止做「努力工作」。使用['CompletableFuture'](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html)。對於[示例](https://www.ibm.com/developerworks/library/j-jvmc3/)。 –

回答

0

根據servlet specification

對於在分佈式環境中(默認值)不舉辦一個servlet, servlet容器必須用每servlet的 聲明只有一個實例。但是,對於實現了SingleThreadModel接口的servlet,servlet容器可能會實例化多個實例來處理沉重的請求負載並將請求序列化到特定實例。

在一個servlet部署標示在部署描述符爲分佈式應用程序 的一部分的情況下,一個容器可以 具有每Java虛擬 機(JVM)的servlet聲明只有一個實例。但是,如果可分發應用程序 中的servlet實現SingleThreadModel接口,則容器可能在 容器的每個JVM中實例化該servlet的多個實例。

此外,here你可以找到關於Tomcat的一些資料:

網絡服務器如Tomcat可以實例化任意多的情況下,一個servlet的 ,雖然數量通常很小(例如,1〜 4)。網絡服務器本身做出決定。

因此,在應用程序中只有一個servlet實例是絕對正常的。

請確保您真的需要重寫HttpServlet.service()方法,因爲,它在javadoc說:

沒有必要重寫此方法