SpringBoot - 第三十三章 | @Async 實現異步調用
同步、異步我們經常用到,在Java中我們大部分時間都是在做同步編程,因為Java天生就是同步的,然而我們在某些場景下是需要考慮吞吐量和延遲,也就是我們經常提起的性能問題,那異步避免不了會被提起。
同步調用/異步調用
- 同步調用:指程序按照定義順序依次執行,每一行程序都必須等待上一行程序執行完成之後才能執行。
- 異步調用:指程序在順序執行時,不等待異步調用的語句返回結果就執行後面的程序。
同步調用範例
建立 SyncTask
建立 測試案例
測試結果
任務一、二、三順序的執行完了,所以說doTaskOne、doTaskTwo、doTaskThree三個函數依照順序執行完成。
異步調用範例
上面的同步調用雖然順利的執行完了三個任務,但是可以看到執行時間比較長,若這三個任務本身之間不存在依賴關係,可以並發執行的話,同步調用在執行效率方面就比較差,可以考慮通過異步調用的方式來並發執行。
我們只需要通過使用@Async註解就能簡單的將原來的同步函數變為異步函數。
建立 AsyncTask
建立 測試案例
測試結果
目前doTaskOne、doTaskTwo、doTaskThree三個函數的時候已經是異步執行了。主程序在異步調用之後,主程序並不會理會這三個函數是否執行完成了,由於沒有其他需要執行的內容,所以程序就自動結束了,導致了不完整或是沒有輸出任務相關內容的情況。
注意:
@Async
所修飾的函數不要定義為static類型,這樣異步調用不會生效。
這邊將程式的註解移除,讓同步與異步的一起執行測試,可以看到異步的程序沒有被結束,正好可以觀察異步的調用狀態。
異步回調範例
為了讓doTaskOne、doTaskTwo、doTaskThree能正常結束,假設我們需要統計一下三個任務並發執行共耗時多少,這就需要等到上述三個函數都完成調動之後記錄時間,併計算結果。
那麼我們如何判斷上述三個異步調用是否已經執行完成呢?我們需要使用CompletableFuture
建立 CompleteAsyncTask
建立 測試案例
測試結果
可以看見透過異步調用,讓任務一、二、三併發執行,且可以做回調來判斷任務完成狀況決定後續事務處理,例:總完成時間。
註:以上參考了
Spring 的 Creating Asynchronous Methods 文章。
DZone 的 Spring Boot: Creating Asynchronous Methods Using @Async Annotation 文章。
程序猿DD 的 Spring Boot中使用@Async实现异步调用 文章。
nealma.com 的 Spring-Boot(十七) Async Of Spring Boot
(十八)SpringBoot2.0使用@Async实现异步调用