介绍
同步操作:
异步操作:
?spring web 异步操作的实现有很多种, 我只学了两种?Callable 和DeferredResult
- Callable : 在程序内部处理
- DeferredResult: 需要处理DeferredResult
案例
Callable<?>使用
@ResponseBody
@RequestMapping("/async01")
public Callable<String> async01() {
System.out.println("主线程开始..." + Thread.currentThread() + "==>" + System.currentTimeMillis());
Callable<String> callable = new Callable<String>() {
@Override
public String call() throws Exception {
System.out.println("副线程开始..." + Thread.currentThread() + "==>" + System.currentTimeMillis());
Thread.sleep(2000);
System.out.println("副线程开始..." + Thread.currentThread() + "==>" + System.currentTimeMillis());
return "Callable<String> async01()";
}
};
System.out.println("主线程结束..." + Thread.currentThread() + "==>" + System.currentTimeMillis());
return callable;
}
DeferredResult<?>使用
自定义DeFerredResultQueue
定义存储异步处理数据的队列
public class DeferredResultQueue {
private static Queue<DeferredResult<Object>> queue = new ConcurrentLinkedQueue<DeferredResult<Object>>();
public static void save(DeferredResult<Object> deferredResult){
queue.add(deferredResult);
}
public static DeferredResult<Object> get( ){
return queue.poll();
}
}
Controller
@ResponseBody
@RequestMapping("/createOrder")
public DeferredResult<Object> createOrder() {
DeferredResult<Object> deferredResult = new DeferredResult<>((long) 10000, "create fail...");
DeferredResultQueue.save(deferredResult);
return deferredResult;
}
@ResponseBody
@RequestMapping("/create")
public String create() {
//创建订单
String order = UUID.randomUUID().toString();
DeferredResult<Object> deferredResult = DeferredResultQueue.get();
deferredResult.setResult(order);
return "success===>" + order;
}
总结
Callable
- 1) spring异步处理,先将Callable提交到TaskExecutor 使用一个隔离的线程进行执行
- 2) DispatcherServlet和所有的Filter退出web容器的线程,但是response 保持打开状态
- 3)Callable 返回结果,SpringMvc 将请求重新派发给容器,恢复之前的处理
- 4)根据Callable返回的结果。 SpringMvc 继续进行试图渲染流程等
流程如下:
preHandle.../springmvc-annotation/async01 主线程开始...Thread[http-bio-8081-exec-3,5,main]==>1513932494700 主线程结束...Thread[http-bio-8081-exec-3,5,main]==>1513932494700 =========DispatcherServlet及所有的Filter退出线程============================
================等待Callable执行========== 副线程开始...Thread[MvcAsync1,5,main]==>1513932494707 副线程开始...Thread[MvcAsync1,5,main]==>1513932496708 ================Callable执行完成==========
================再次收到之前重发过来的请求======== preHandle.../springmvc-annotation/async01 postHandle...(Callable的之前的返回值就是目标方法的返回值) afterCompletion...
异步的拦截器: 1)、原生API的AsyncListener 2)、SpringMVC:实现AsyncHandlerInterceptor;
DeferredResult
执行流程(与Callable一致,不做翻译了,直接看英文吧?)
The controller returns a DeferredResult and saves it in some in-memory queue or list where it can be accessed.
Spring MVC calls request.startAsync().
Meanwhile, the DispatcherServlet and all configured filters exit the request processing thread, but the response remains open.
The application sets the DeferredResult from some thread, and Spring MVC dispatches the request back to the Servlet container.
The DispatcherServlet is invoked again, and processing resumes with the asynchronously produced return value.