【问题标题】:How to run long running process using servlet如何使用 servlet 运行长时间运行的进程
【发布时间】:2016-08-10 19:47:14
【问题描述】:

我有一种情况,我需要启动一个运行 4 小时的任务。我正在使用 servlet 来启动该过程。但是我遇到了内存泄漏异常。

Aug 10, 2016 2:08:05 PM org.apache.catalina.core.StandardContext reload
INFO: Reloading Context with name [/] has started
Aug 10, 2016 2:08:05 PM org.apache.catalina.core.StandardWrapper unload
INFO: Waiting for 1 instance(s) to be deallocated for Servlet [Servlet]
Aug 10, 2016 2:08:06 PM org.apache.catalina.core.StandardWrapper unload
INFO: Waiting for 1 instance(s) to be deallocated for Servlet [Servlet]
Aug 10, 2016 2:08:07 PM org.apache.catalina.core.StandardWrapper unload
INFO: Waiting for 1 instance(s) to be deallocated for Servlet [DayZeroServlet]
Aug 10, 2016 2:08:07 PM org.apache.catalina.loader.WebappClassLoaderBase clearReferencesThreads
WARNING: The web application [xxx#Day0MS] is still processing a request that has yet to finish. This is very likely to create a memory leak. You can control the time allowed for requests to finish by using the unloadDelay attribute of the standard Context implementation. Stack trace of request processing thread:
java.net.SocketOutputStream.socketWrite0(Native Method)
java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:109)

下面是代码,我正在使用

protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
    PrintWriter out = response.getWriter();
    if (!GehDAO.getProcessFlag()) {
        GehDAO.updateProcessFlag(true);
        out.println("Transformation started  ...");
        closeWriter(out);
        execute();  // This step start the long running process
    }
    else {
        out.println("Transformation Already Running  ...");
        closeWriter(out);
    }
}

有没有办法在单独的进程中运行 execute() 方法?

我想在一个月内运行一次或两次这个 servlet,以启动长时间运行的进程。

【问题讨论】:

  • 请注意您的代码不是线程安全的。

标签: java multithreading servlets


【解决方案1】:

您不能将execute() 调用封装到一个线程中吗?

new Thread(() -> execute()).start();

或者对于较早的 Java8 之前的版本:

new Thread(new Runnable() {
    public void run() { execute(); }
}).start();

附注:确保您管理关机。您通常可以使用ServletContextListener 执行此操作。基本上,如果上下文被破坏,请在长时间运行的线程上设置一个布尔标志,让它知道它需要停止,因为应用服务器正在等待它完成以关闭。

【讨论】:

  • 基本上就是这个。分叉一个新线程并让它旋转。如果您审核他们的任务进度以便他们可以监控其进度,那么您的最终用户将获得奖励积分;我发现 MongoDB 很适合存储这样的东西,但任何其他数据库都应该可以工作。此外,使用数据库将允许您实现任务队列,这样您的用户就不会启动 18 万亿个并行线程。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-08
  • 2023-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多