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

2、实现异步请求需要使用AsynContext对象。新建一个实现异步请求的Servlet。
package com.gwolf;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(value="/async")
public class HelloAsyncServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
}
public void sayHello() throws Exception {
System.out.println(Thread.currentThread()+ "processing.....");
Thread.sleep(3000);
}
}

3、如果要支持异步请求,需要在WebServlet注解中开启异步支持。
@WebServlet(value="async",asyncSupported=true)

4、接下来就是开启异步模式,进行业务逻辑异步处理。
package com.gwolf;
import java.io.IOException;
import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(value="/async",asyncSupported=true)
public class HelloAsyncServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("主线程开始。。。。" + Thread.currentThread());
AsyncContext async = req.startAsync();
async.start(new Runnable() {
@Override
public void run() {
try {
System.out.println("副线程开始。。。。" + Thread.currentThread());
sayHello();
async.complete();
ServletResponse response = async.getResponse();
response.getWriter().write("hello async...");
System.out.println("副线程结束。。。。" + Thread.currentThread());
} catch (Exception e) {
e.printStackTrace();
}
}
});
System.out.println("主线程结束。。。。" + Thread.currentThread());
}
public void sayHello() throws Exception {
System.out.println(Thread.currentThread()+ "processing.....");
Thread.sleep(3000);
}
}

5、运行应用,查看主线程和异步线程的执行情况。

6、这样异步请求就不会占用主线程池的线程,从而影响程序的性能。
