在Servlet3.0之前,Servlet采用Thread-Per-Request的方式处理请求
即每次Http请求都有一个线程从头到尾负责处理
如果一个请求需要进行IO操作,比如访问数据库、调用第三方服务接口等,那么其所对应的线程将同步地等待IO操作完成,而IO操作是非常慢的,所以此时的线程不能及时的释放回线城市以供后续使用,在并发量越来越大的情况下,这将带来严重的性能问题。即便是像Spring这样的高层框架也脱离不了这样的束缚。因为他们都是建立在servlet之上的。为了解决这样的问题,Servlet3.0引入了异步处理,然后在Servlet3.1中又引入了非阻塞IO来进一步增强异步处理的性能。

同步的例子:
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println(Thread.currentThread()+"start...");
try {
sayHello();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
resp.getWriter().write("hello");
System.out.println(Thread.currentThread()+"end...");
}
public void sayHello() throws InterruptedException {
System.out.println(Thread.currentThread()+"processing...");
Thread.sleep(3000);
}
}
请求之后:

开启异步:
@WebServlet(value = "/async", asyncSupported = true) // true 就可以支持异步了 public class HelloAsyncServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("主线程...."+Thread.currentThread()); AsyncContext startAsync = req.startAsync(); // 业务逻辑进行异步处理;开启异步处理 startAsync.start(new Runnable() { @Override public void run() { try { System.out.println("副线程开启...."+Thread.currentThread()+Thread.currentThread()+"==>"+System.currentTimeMillis()); sayHello(); //获取到异步的上下文 AsyncContext asyncContext = req.getAsyncContext(); // 获取响应 ServletResponse response = asyncContext.getResponse(); //获取交出去的响应 response.getWriter().write("hello toov5 async"); startAsync.complete(); //异步调用完毕 开始给予响应 System.out.println("副线程结束...."+Thread.currentThread()+"==>"+System.currentTimeMillis()); } catch (InterruptedException | IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); System.out.println("主线程结束..."+Thread.currentThread()+"==>"+System.currentTimeMillis()); } public void sayHello() throws InterruptedException { System.out.println(Thread.currentThread() + "processing..."); Thread.sleep(3000); } }
结果:


如果开启了异步处理 当前tomcat线程池里的线程立马结束,交给新的异步处理的线程池中的线程去处理
当前这个没有去维护异步处理的线程池。

springmvc 会维护一个异步处理的线程池
这样主线程释放 等待下一个请求