《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進行測試:
執行異步:
同步執行: