【问题标题】:AsyncContext infinite thread terminationAsyncContext 无限线程终止
【发布时间】:2016-01-04 14:23:32
【问题描述】:

我有点困惑 servlet 容器如何在应用程序取消部署阶段终止 AsyncContext 或只是超时。例如应用程序开发人员有以下代码sn-p:

@WebServlet(name = "MyServlet", urlPatterns = "/myServlet", asyncSupported = true)
public class MyServlet extends HttpServlet {
    private static Logger log = Logger.getLogger(MyServlet.class);

    @Override  
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        AsyncContext asyncContext = request.startAsync();
        asyncContext.start(new Runnable() {  
            @Override  
            public void run() {  
                log.debug("Start of Task");  

                try {
                    while(true) {
                        response.getWriter().println("random text");
                        Thread.sleep(100);
                    }
                }catch(Exception e) {
                    log.warn("Async processing exception: " + e.getMessage);
                }
                asyncContext.complete();  

                log.debug("End of Task");  
            }  
        });
    }  
}

这里是 AsyncContext 开始可运行,永远不会结束,或者直到在 while 循环中抛出一些异常。所以问题是容器将如何终止运行如此无限可运行的线程。想到的唯一想法是thread.stop();,但它已被弃用。我几乎可以肯定容器不会调用 thread.interrupt();,因为它不保证引用 javadoc 的线程中断,并且开发人员在这里设置条件 while-true 而不是 while-not-interrupted 因此不对这种情况负责。

任何建议表示赞赏。

【问题讨论】:

  • 为什么容器应该终止这样一个可运行的(如果它故意使用无限while循环)?
  • @SabirKhan 如果管理员决定使用 CLI lib/web UI 或其他方式从 sevlet 容器中取消部署应用程序怎么办。让线程继续运行?
  • 您可以覆盖destroy 方法并按照您想要的方式完成您的对象。

标签: java multithreading jakarta-ee asynchronous servlet-3.0


【解决方案1】:

如果应用程序开发人员故意让它无限循环,则 Web 容器无法强制关闭线程。

幸运的是,应用程序程序员可以使用多种机制来确保AsyncContext 不会无限运行。我脑海中的一些想法是:

  • 通过AsyncContext.setTimeout(long)为请求设置超时
  • 重写 Servlet destory() 方法并调用 AsyncContext.complte(),这将在每个侦听器上调用 AsyncListener.onComplete(AsyncEvent)。然后,您可以在使用 AsyncContext.addListener(AsyncListener) 添加侦听器后附加一个停止进程的侦听器。
  • 在 servlet 类中手动存储对线程的引用并在 Servlet destory()method 中停止它。

主要思想是,如果您要编写一个无限循环的线程(并且您关心在关闭时停止线程),您将需要编写一些代码来确保您的线程正确停止。

AsyncContext.start(Runnable) 使用的线程有一个机会来自托管线程池:

AsyncContext.start(Runnable):使容器调度一个线程(可能来自托管线程池)来运行指定的 Runnable。

但是,由于规范对此并不严格,您需要手动调查您的 Java EE 实现如何解释该位,以查看它是否使用托管线程。如果是这样,当应用服务器停止时,您的线程可能会自动为您停止。

【讨论】:

  • 您好,感谢您的建议。我想你回答了我的主要问题。如果我错了,请纠正我 - 应用程序开发人员完全负责线程终止,从而负责防止内存泄漏(使用您上面描述的三个选项中的任何一个)。
  • 是的,如果您有不受容器管理的资源(即由AsyncContext.start(Runnable) 创建的非托管线程),则需要手动清理。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-17
  • 1970-01-01
  • 2017-05-23
  • 1970-01-01
相关资源
最近更新 更多