这些天我正在学习Servlet3.0异步特性,它的主要思想是释放绑定到Http线程到另一个线程的任务,这样Http线程可以返回到Http线程池(而不是阻塞长任务处理),这样您的应用程序就可以更快地响应。这里一切都很好。
我找到了两种方法来处理这个耗时的任务
acontext.start(new Runnable() {...}) gets a new thread from the container.我的问题是:
发布于 2014-06-04 08:35:16
不同之处在于:
(1)在servlet线程池中执行缓慢的任务,导致servlet池饥饿(至少Tomcat/Jetty是这样的)。这意味着,如果用serviceImpl(req, resp, adapter, context, isNotLeakScan);替换Thread.sleep(Long.MAX_VALUE);,并尝试从浏览器连接Tomcat 200次(默认线程数为200个),那么Tomcat将永远挂起,不再接受任何HTTP连接。
(2)手工生成每个任务的线程。
您通常不希望手动生成线程、轮询队列等。相反,您可以使用Executors框架,它在外壳下具有队列实现,并且基于内部线程池。
@WebServlet(urlPatterns = {"/slowServlet"}, asyncSupported = true)
public class SlowServlet extends javax.servlet.http.HttpServlet {
protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
final AsyncContext acontext = request.startAsync();
ServletContext appScope = request.getServletContext();
((Executor) appScope.getAttribute("executor")).execute(() -> {
try {
Thread.sleep(10000); // your slow running task
acontext.getResponse().getWriter().print("Done");
} catch (Exception e) {
e.printStackTrace();
}
});
}
}servlet上下文侦听器是(线程池的大小在这里是硬编码的)
@WebListener
public class ExecutorListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent sce) {
Executor executor = Executors.newFixedThreadPool(10);
sce.getServletContext().setAttribute("executor", executor);
}
public void contextDestroyed(ServletContextEvent sce) {
// add executor fancy shutdown logic here
}
}https://stackoverflow.com/questions/24030366
复制相似问题