Apache Tomcat Servlet线程未完成

时间:2013-05-31 07:53:15

标签: java multithreading tomcat servlets lifecycle

我已经编写了一个部署在tomcat中的servlet。

public class myServlet extends HttpServlet {
    public int NumberOfThreads = 0;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    System.out.println(NumberOfThreads);
    NumberOfThreads++;
    ....
    ..a lot of code..
    ....
    NumberOfThreads--;
    }
}

现在,当我收到太多请求时,NumberOfThreads会继续上升并且永远不会再次下降。我的问题是每个请求在离开之前必须执行一些任务。

我只是不明白为什么会这样。是不是有些线程在路上丢失了?我真的需要每个请求说再见。

由于

4 个答案:

答案 0 :(得分:1)

正如您所说的那样需要很长时间并且请求被取消(在您的评论中):是的,整个doGet将被执行,即使用户取消了请求:请求取消仅限在HTTP级别上。但是,当取消请求时,HTTP连接可能会关闭,导致实际想要写入响应的输出流时出现异常。

结合已经给出的其他答案:

  • 您需要同步计数器的修改(参见didxga的回答)
  • 可能有更好的方法来解决你的问题(如Ravi Thapliyal所述)
  • 最后使用try {...} {...}确保您实际减少了计数器
  • 将代码从servlet移到适当的非UI类
  • ,使代码更易于维护

伪代码:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    try {
        synchronized(this){NumberOfThreads++;}
        doSomething();
    } finally {
        synchronized(this){NumberOfThreads--;}
    }
}

另外,请注意在实际的http连接器线程中长时间执行会阻止所有后续的http请求 - 触发后台处理并在稍后的HTTP请求中查询后台进程可能是个好主意。这样,您也可以对多个调用进行排队,而不是同时启动大量后台线程。请记住,HTTP请求处理程序数量有限。

我假设try / finally将是你的主要问题(或代码中的无限循环) - 同步将解决罕见的竞争条件,特别是当你谈到很多时在这个servlet中执行的代码。

答案 1 :(得分:0)

您需要将修改同步到NumberOfThreads

    public class myServlet extends HttpServlet {
        public int NumberOfThreads = 0;

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println(NumberOfThreads); synchronized(this){NumberOfThreads++;} .... ..a lot of code.. .... synchronized(this){NumberOfThreads--;} } }

答案 2 :(得分:0)

不同的servlet线程正在缓存NumberOfThreads。您必须将其标记为volatile

public volatile int NumberOfThreads = 0;

但是,我觉得有更好的方法来做你可能希望用这段代码实现的目标。

答案 3 :(得分:0)

你做错了。

System.out.println(ManagementFactory.getThreadMXBean().getThreadCount());

或者,只需使用JMX / JConsole。