Servlet似乎没有以线程方式执行

时间:2010-05-06 09:31:03

标签: java tomcat servlets multithreading

我使用运行servlet的Tomcat开发了一个简单的服务器。

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

4 个答案:

答案 0 :(得分: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
    }
  }
}

在上面的示例中,一次只有一个线程可以执行相同的请求方法,尽管可以(例如)一个线程执行doPost()而另一个线程执行doGet()

如果您不明白为什么会这样,那么我建议您在进一步研究问题之前先阅读Java中的并发编程。

答案 1 :(得分:1)

问题在于您的测试客户端。它同步触发请求。它应该异步触发请求,然后servlet将能够执行相同的操作:)

大致相同的问题在4天前被问到,我已经发布了一个代码示例的答案,测试客户端应该如何:Servlet requests are executed sequentially for no apparent reason in Glassfish v3。您可能会发现它也很有用。

答案 2 :(得分:0)

确保您的请求使用不同的HTTP连接并检查您的tomcat配置是否允许超过1个线程(默认情况下确实如此,所以除非您更改它,否则应该没问题。)

答案 3 :(得分:0)

一旦你在Tomcat上运行app(而不是在调试模式下通过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秒后返回等等......