我有点困惑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因此不对此负责情况下。
任何建议表示赞赏。
答案 0 :(得分:1)
如果应用程序开发人员故意使其无限循环,则Web容器无法强制关闭某个线程。
幸运的是,应用程序员可以使用多种机制来确保AsyncContext
无法无限运行。我头脑中的一些想法是:
AsyncContext.setTimeout(long)
destory()
方法并调用AsyncContext.complte()
,它将在每个侦听器上调用AsyncListener.onComplete(AsyncEvent)
。然后,您可以在使用AsyncContext.addListener(AsyncListener)
添加侦听器后附加一个停止进程的侦听器。destory()
方法中停止它。主要的想法是,如果你要编写一个无限循环的线程(并且你关心在关闭时停止线程),你将需要编写一些代码来确保你的线程被正确停止。
成功 AsyncContext.start(Runnable)
使用的线程来自托管线程池:
AsyncContext.start(Runnable)
:使容器可能从托管线程池调度一个线程来运行指定的Runnable。
但是,由于规范并不牢固,您需要手动调查Java EE实现如何解释此位以查看它是否使用托管线程。如果是,则当应用服务器停止时,您的线程可能会自动停止。