【1】Callable
① 概述
其原理如下:
控制器返回Callable
Spring异步处理,将Callable 提交到 TaskExecutor 使用一个隔离的线程进行执行
DispatcherServlet和所有的Filter退出web容器的线程,但是response 保持打开状态;
Callable返回结果,SpringMVC将请求重新派发给容器,恢复之前的处理;
根据Callable返回的结果。SpringMVC继续进行视图渲染流程等(从收请求-视图渲染)。
② 代码示例
@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; }
测试如下:
【2】DeferredResult
一旦启用了异步请求处理功能 ,控制器就可以将返回值包装在DeferredResult
,控制器可以从不同的线程异步产生返回值。
优点就是可以实现两个完全不相干的线程间的通信。
① 创建一个存储DeferredResult的实例
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(); } }
② 两个请求方法
@ResponseBody @RequestMapping("/createOrder") public DeferredResult<Object> createOrder(){ DeferredResult<Object> deferredResult = new DeferredResult<>((long)3000, "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; }
http://localhost:8080/springmvc-annotation/create请求创建order,并给deferredResult赋值。
http://localhost:8080/springmvc-annotation/createOrder请求获取order,有结果返回,超出等待时间返回创建失败。