我来自Java SE背景,我做了一些servlet教程并阅读了Head First JSP& servlet的。我现在正在阅读关于异步支持的JavaWorld.com文章,但我不太明白。
异步是什么? Ajax和Servlet Async之间有什么区别?
P.S我有一个带有ajax的PHP背景,我知道这个概念,但我还没试过它用java
答案 0 :(得分:83)
在传统的Servlet模型中,通常情况是1个请求对应于1个线程。
这些线程通常来自由Servlet容器管理的池。 Servlet容器只能处理新请求,只要它在此池中有空闲线程即可。只要您自己的代码忙于处理请求,该线程就不是免费的。
在某些情况下,打破这个模型可能是值得的。发生的事情是请求通过这样的Servlet容器管理线程到达Servlet,然后您的代码要求异步执行。然后,您可以从Servlet请求返回,并且将释放容器线程。
与同步请求处理相反,这不会提交任何响应,也不会关闭连接。相反,您可以将异步上下文移交给另一个线程池,该线程池可以将其拾取,并且当某个线程可以自由处理它时,为它提供服务并且能够写入响应。
一个例子:
@WebServlet(urlPatterns = "/somepath", asyncSupported = true)
public class AsyncServlet extends HttpServlet {
@EJB
private AsyncBean asyncBean;
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
AsyncContext asyncContext = request.startAsync();
// The following line will not block and return immediately
asyncBean.doAsyncStuff(asyncContext);
} // Shortly after this method has ended, thread will be returned to pool
}
将AsyncBean
实施为:
@Stateless
public class AsyncBean {
@Asynchronous
public void doAsyncStuff(AsyncContext asyncContext) throws IOException {
asyncContext.getResponse().getWriter().write("test");
}
}
在上面的代码中,从AsyncServlet#doGet()
方法返回后不久,Servlet线程将返回到池中。执行AsyncBean#doAsyncStuff()
的'request'(任务)将被放入队列中供EJB线程池接收。
为什么以及何时使用它的答案并非如此简单。如果您只想保留线程,那么在上面的情况下,您将从一个线程池中为另一个线程池交换一个线程(在这种情况下是Servlet池与EJB异步池),并且净效益不会那么多。你也可以给你的Servlet线程池一个额外的线程。
在更高级的方案中,您可以对请求进行更细粒度的管理;将它们分成多个任务,并为这些任务提供线程池服务。例如。想象一下10个线程所处理的10MB文件的100个下载请求,循环让每次请求发送100KB的文件。
另一个应用程序是需要等待来自外部系统的数据的请求,并且此外部系统能够发送可以中继回请求者的消息。即数据库调用在这里没有意义,因为无论如何你都需要另一个线程来等待响应。然后你会再次为另一个线程换一个线程。但是,如果您需要等待收到传入的电子邮件,那么一个线程可以等待任何电子邮件并将其转发给任何已暂停的请求。