0

我已经编写了一个部署在 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

4 回答 4

1

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

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

  • 您需要同步对计数器的修改(参见 didxga 的回答)
  • 可能有更好的方法来解决您的问题(如 Ravi Thapliyal 所述)
  • 使用 try{ ... } finally { ... } 确保您实际减少计数器
  • 通过将代码从 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 中执行的大量代码时。

于 2013-05-31T10:49:31.143 回答
1

你这样做是不对的。

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

或者,只需使用 JMX/JConsole。

于 2013-05-31T08:18:18.367 回答
0

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

public volatile int NumberOfThreads = 0;

但是,我有一种感觉,有更好的方法来做你可能想用这段代码实现的目标。

于 2013-05-31T07:59:57.190 回答
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--;} } }
于 2013-05-31T07:59:37.393 回答