这是我对这个问题的结论:
servilla中的“Vanilla”线程
这里是响应发送后成功执行的示例代码:
protected void doPost(final HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
final long startTime = System.currentTimeMillis(); //Start time to compare easily
// MY ASYNC JOB
Thread t1 = new Thread(new Runnable() {
public void run()
{
try {
Thread.sleep(10000);
System.out.println("Long operation done. / " + (System.currentTimeMillis() - startTime));
} catch (InterruptedException e) {
e.printStackTrace();
}
}});
t1.start();
// END OF MY ASYNC
// Servlet code here
System.out.println("Will send the response. / " + (System.currentTimeMillis() - startTime));
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
}
结果:我在邮差中收到了17ms的答复
会发送回复 . / 1长时间操作完成 . / 10011
servlet中的Spawn线程是针对Java EE规范的,而EJB在内部不起作用 . See here或here . 以这种方式使用线程可能导致线程饥饿 . 每个服务器上都不允许这样做(Tomcat不会阻止这种情况) .
可扩展性是 Contract 性的,了解我和读者的所有选项真的很有趣 . 而且我不知道我将在哪台服务器上托管我的webapp!
ManagedExecutorService
ManagedExecutorService是Java EE 7的一部分 . 在我的例子中,项目以Java EE 6环境为目标,因此我使用了ExecutorService . 早些时候我遇到了一个问题:我无法在异步中访问请求的正文,我发现this:
Servlet 3.1中引入的异步请求体读取概念
但Servlet 3.1也是Java EE 7 . 所以我的runnable构造函数请求请求体作为String .
这是ServletContextListener的示例代码:
public void contextInitialized(ServletContextEvent event) {
//Executor
executor = Executors.newCachedThreadPool();
//Init Context
app = event.getServletContext();
app.setAttribute("executor", executor);
}
//Do not forget to implements contextDestroyed !
public void contextDestroyed(ServletContextEvent event) {
try {
executor.shutdown();
while(!executor.awaitTermination(10, TimeUnit.SECONDS)){
System.out.println("executor.awaitTermination");
};
} catch (InterruptedException e) {
e.printStackTrace();
}
}
而我的servlet:
protected void doPost(final HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
final long startTime = System.currentTimeMillis(); //Start time to compare easily
//Get my executor service and run a new async task
ExecutorService serv = (ExecutorService) this.getServletContext().getAttribute("executor");
serv.execute(new testAsync(startTime));
// Servlet code here
System.out.println("Will send the response. / " + (System.currentTimeMillis() - startTime));
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
}
//My runnable
private class testAsync implements Runnable{ //Use Callable for Java 7+
private long startTime;
//Prior to Servlet 3.1, you have to give the request body instead of using asyncContext
public testAsync(long pstart){
this.startTime = pstart;
}
@Override
public void run(){
try {
Thread.sleep(10000);
System.out.println("Long operation done. / " + (System.currentTimeMillis() - this.startTime));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
这个例子对我来说似乎是最好的解决方案,因为我必须在我的异步任务中进行多线程处理 . 我使用Tomcat作为dev,但如果你使用其他东西,你必须使用ManagedExecutorService,因为它可能会阻止你在servlet中启动线程 .
我也很惊讶没有在stackoverflow上找到一个简单的快速示例 . 由于this article,我能够编码 .
编辑:我此时并不知道JMS,并将继续研究它是否适合我的问题