一、原理:
1)同步请求

2)异步请求

例:
@WebServlet(value="/hello", asyncSupported=true) public class HelloServlet extends HttpServlet{ private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1、支持异步处理asyncSupported=true //2、开启异步模式 System.out.println("主线程start.." + Thread.currentThread() + "" + System.currentTimeMillis()); AsyncContext startAsync = req.startAsync(); //3、业务逻辑进行异步处理 startAsync.start(new Runnable() { @Override public void run() { try { System.out.println("副线程start.." + Thread.currentThread() + "" + System.currentTimeMillis()); sayHello(); //获取到异步上下文 startAsync.getResponse().getWriter().write("hello async...."); System.out.println("副线程end.." + Thread.currentThread() + "" + System.currentTimeMillis()); //4、异步请求结束 startAsync.complete(); } catch (Exception e) { e.printStackTrace(); } } }); System.out.println("主线程end.." + Thread.currentThread() + "" + System.currentTimeMillis()); } protected void sayHello() throws InterruptedException { Thread.sleep(3000); System.out.println("---sayHello---" + Thread.currentThread() + "" + System.currentTimeMillis()); } }
请求/hello打印:
主线程start..Thread[qtp1020923989-21,5,main]1560610474890 主线程end..Thread[qtp1020923989-21,5,main]1560610474893 副线程start..Thread[qtp1020923989-25,5,main]1560610474893 ---sayHello---Thread[qtp1020923989-25,5,main]1560610477893 副线程end..Thread[qtp1020923989-25,5,main]1560610477899
web容器主线程收到请求后立马结束,启动一个副线程继续处理业务逻辑
二、SpringMVC异步请求
处理过程:



@RequestMapping(value="/async") public Callable<String> async() { System.out.println("主线程start..." + Thread.currentThread() + "==>" + System.currentTimeMillis()); Callable<String> callable = new Callable<String>() { @Override public String call() throws Exception { System.out.println("副线程start..." + Thread.currentThread() + "==>" + System.currentTimeMillis()); Thread.sleep(3000); System.out.println("副线程end..." + Thread.currentThread() + "==>" + System.currentTimeMillis()); return "Callable async"; } }; System.out.println("主线程end..." + Thread.currentThread() + "==>" + System.currentTimeMillis()); return callable; }
控制台打印:
preHandle... 主线程start...Thread[qtp1020923989-23,5,main]==>1560611533336 主线程end...Thread[qtp1020923989-23,5,main]==>1560611533337 副线程start...Thread[MvcAsync1,5,main]==>1560611533342 副线程end...Thread[MvcAsync1,5,main]==>1560611536343 preHandle... postHandle... afterCompletion