一、原理:

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