Spring注解开发系列Ⅸ --- 异步请求

一. Servlet中的异步请求

在Servlet 3.0之前,Servlet采用Thread-Per-Request的方式处理请求,即每一次Http请求都由某一个线程从头到尾负责处理。如果要处理一些IO操作,以及访问数据库,调用第三方服务接口时,这种做法是十分耗时的。可以用代码测试一下:

同步方式处理: 

@WebServlet("/helloServlet")
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) { e.printStackTrace(); } resp.getWriter().write("hello..."); System.out.println(Thread.currentThread()+" end ...."); } public void sayHello() throws InterruptedException { Thread.sleep(3000); } }

以上代码,执行了一个3秒的方法,主线程在3秒方法执行完之后,才得到释放,这样处理效率非常不高。在Servlet 3.0引入了异步处理,然后在Servlet 3.1中又引入了非阻塞IO来进一步增强异步处理的性能。

异步方式处理业务逻辑:

@WebServlet(value = "/asyncServlet",asyncSupported = true)
public class AsyncHelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println(Thread.currentThread()+"主线程start..."+System.currentTimeMillis());
        //1.支持异步处理 asyncSupported = true
        //2.开启异步
        AsyncContext asyncContext = req.startAsync();
        //3.业务逻辑业务处理
        asyncContext.start(new Runnable() { @Override public void run() { try { System.out.println(Thread.currentThread()+"副线程start..."+System.currentTimeMillis()); sayHello(); asyncContext.complete(); //4.获取响应 ServletResponse response = asyncContext.getResponse(); response.getWriter().write("hello,async..."); System.out.println(Thread.currentThread()+"副线程end..."+System.currentTimeMillis()); } catch (InterruptedException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }); System.out.println(Thread.currentThread()+"主线程end..."+System.currentTimeMillis()); //测试结果,主线程接受请求处理,并立即得到释放,副线程处理业务逻辑 /** * Thread[http-apr-8080-exec-9,5,main]主线程start...1545911791802 * Thread[http-apr-8080-exec-9,5,main]主线程end...1545911791806 * Thread[http-apr-8080-exec-10,5,main]副线程start...1545911791806 * Thread[http-apr-8080-exec-10,5,main]副线程end...1545911794807 */ } public void sayHello() throws InterruptedException { Thread.sleep(3000); }

上面的代码中,主线程在Servlet被执行到时,立刻得到了释放,然后在副线程中调用了sayHello方法,3秒后副线程得到释放,这就是异步Servlet最简单的一个demo演示。

猜你喜欢

转载自www.cnblogs.com/wangxiayun/p/10187135.html