AsyncContext无限线程终止

时间:2016-01-04 14:23:33

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

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

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

任何建议表示赞赏。

1 个答案:

答案 0 :(得分:1)

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

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

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

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

成功 AsyncContext.start(Runnable)使用的线程来自托管线程池:

  

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

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