《JavaEE开发的颠覆者: Spring Boot实战》系列读书笔记
Spring boot异步调用@Async
什么是异步调用?
- 异步调用是相对于同步调用而言的,同步调用是指程序按预定顺序一步步执行,每一步必须等到上一步执行完后才能执行,异步调用则无需等待上一步程序执行完即可执行。
如何实现异步调用?
-
多线程是一种实现异步调用的方式,在非spring目项目中我们要实现异步调用的就是使用多线程方式,可以自己实现Runable接口或者集成Thread类,或者使用Executors线程池。
SpringBoot中则提供了很方便的方式执行异步调用,一个
@Async
就可搞定。
开始使用
- 在启动类上加上
@EnableAsync
注解开启异步
controller层
-
写一个同步接口和异步接口,在需要异步的执行方法上添加@Async注解
@RequestMapping("async") @RestController public class AsyncTaskController { @Autowired private AsyncTask asyncTask; @RequestMapping(value = "doTask",method = RequestMethod.GET) public String doTask() throws InterruptedException{ long currentTimeMillis = System.currentTimeMillis(); asyncTask.task1(); asyncTask.task2(); asyncTask.task3(); long currentTimeMillis1 = System.currentTimeMillis(); System.out.println("异步任务总耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms"); return "success"; } @RequestMapping("justDo") public String justDo() throws InterruptedException{ long currentTimeMillis = System.currentTimeMillis(); task1(); task2(); task3(); long currentTimeMillis1 = System.currentTimeMillis(); System.out.println("任务总耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms"); return "success"; } @RequestMapping("doTaskSuccess") public String doTaskSuccess() throws InterruptedException{ long currentTimeMillis = System.currentTimeMillis(); Future<String> task1 = asyncTask.task1s(); Future<String> task2 = asyncTask.task2s(); Future<String> task3 = asyncTask.task3s(); String result = null; for (;;) { if(task1.isDone() && task2.isDone() && task3.isDone()) { // 三个任务都调用完成,退出循环等待 break; } //Thread.sleep(1000); } long currentTimeMillis1 = System.currentTimeMillis(); System.out.println("异步任务总耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms"); return "success"; } public String threadAsynchSayHello() { Runnable runnable = ()-> { try { long currentTimeMillis = System.currentTimeMillis(); Thread.sleep(1000); long currentTimeMillis1 = System.currentTimeMillis(); System.out.println("任务三耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms"); } catch (InterruptedException e) { e.printStackTrace(); } }; System.out.println(Thread.currentThread().getName()+" 开启新线程"); new Thread(runnable).start(); return "success"; } public void task1() throws InterruptedException{ long currentTimeMillis = System.currentTimeMillis(); Thread.sleep(1000); long currentTimeMillis1 = System.currentTimeMillis(); System.out.println("任务一耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms"); } public void task2() throws InterruptedException{ long currentTimeMillis = System.currentTimeMillis(); Thread.sleep(1000); long currentTimeMillis1 = System.currentTimeMillis(); System.out.println("任务二耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms"); } public void task3() throws InterruptedException{ long currentTimeMillis = System.currentTimeMillis(); Thread.sleep(1000); long currentTimeMillis1 = System.currentTimeMillis(); System.out.println("任务三耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms"); } }
异步任务类
-
将异步任务单独放到一个类中
@Component public class AsyncTask { /** * 异步-无返回值 * @throws InterruptedException */ @Async public void task1() throws InterruptedException{ long currentTimeMillis = System.currentTimeMillis(); Thread.sleep(1000); long currentTimeMillis1 = System.currentTimeMillis(); System.out.println("任务一耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms"); } @Async public void task2() throws InterruptedException{ long currentTimeMillis = System.currentTimeMillis(); Thread.sleep(1000); long currentTimeMillis1 = System.currentTimeMillis(); System.out.println("任务二耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms"); } @Async public void task3() throws InterruptedException{ long currentTimeMillis = System.currentTimeMillis(); Thread.sleep(1000); long currentTimeMillis1 = System.currentTimeMillis(); System.out.println("任务三耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms"); } }
-
如何知道异步任务什么时候执行完,执行的结果怎样呢?可以采用添加Fature回调方式判断
/** * 异步- future回调方式 * @return * @throws InterruptedException */ @Async public Future<String> task1s() throws InterruptedException{ long currentTimeMillis = System.currentTimeMillis(); Thread.sleep(1000); long currentTimeMillis1 = System.currentTimeMillis(); System.out.println("任务一耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms"); return new AsyncResult<String>("任务一执行完毕"); } @Async public Future<String> task2s() throws InterruptedException{ long currentTimeMillis = System.currentTimeMillis(); Thread.sleep(2000); long currentTimeMillis1 = System.currentTimeMillis(); System.out.println("任务二耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms"); return new AsyncResult<String>("任务二执行完毕"); } @Async public Future<String> task3s() throws InterruptedException{ long currentTimeMillis = System.currentTimeMillis(); Thread.sleep(3000); long currentTimeMillis1 = System.currentTimeMillis(); System.out.println("任务三耗时:"+(currentTimeMillis1-currentTimeMillis)+"ms"); return new AsyncResult<String>("任务三执行完毕"); }
用postman进行测试:
执行异步:
同步执行: