Like Share Discussion Bookmark Smile

J.J. Huang   2019-04-21   Spring Boot   瀏覽次數:

SpringBoot - 第三十三章 | @Async 實現異步調用

同步、異步我們經常用到,在Java中我們大部分時間都是在做同步編程,因為Java天生就是同步的,然而我們在某些​​場景下是需要考慮吞吐量和延遲,也就是我們經常提起的性能問題,那異步避免不了會被提起。

同步調用/異步調用

  • 同步調用:指程序按照定義順序依次執行,每一行程序都必須等待上一行程序執行完成之後才能執行。
  • 異步調用:指程序在順序執行時,不等待異步調用的語句返回結果就執行後面的程序。

同步調用範例

建立 SyncTask

建立 測試案例

測試結果

任務一、二、三順序的執行完了,所以說doTaskOne、doTaskTwo、doTaskThree三個函數依照順序執行完成。


異步調用範例

上面的同步調用雖然順利的執行完了三個任務,但是可以看到執行時間比較長,若這三個任務本身之間不存在依賴關係,可以並發執行的話,同步調用在執行效率方面就比較差,可以考慮通過異步調用的方式來並發執行。

我們只需要通過使用@Async註解就能簡單的將原來的同步函數變為異步函數。

建立 AsyncTask

建立 測試案例

測試結果

目前doTaskOne、doTaskTwo、doTaskThree三個函數的時候已經是異步執行了。主程序在異步​​調用之後,主程序並不會理會這三個函數是否執行完成了,由於沒有其他需要執行的內容,所以程序就自動結束了,導致了不完整或是沒有輸出任務相關內容的情況。

注意: @Async所修飾的函數不要定義為static類型,這樣異步調用不會生效。

這邊將程式的註解移除,讓同步與異步的一起執行測試,可以看到異步的程序沒有被結束,正好可以觀察異步的調用狀態。


異步回調範例

為了讓doTaskOne、doTaskTwo、doTaskThree能正常結束,假設我們需要統計一下三個任務並發執行共耗時多少,這就需要等到上述三個函數都完成調動之後記錄時間,併計算結果。

那麼我們如何判斷上述三個異步調用是否已經執行完成呢?我們需要使用CompletableFuture來返回異步調用的結果。

建立 CompleteAsyncTask

建立 測試案例

測試結果

可以看見透過異步調用,讓任務一、二、三併發執行,且可以做回調來判斷任務完成狀況決定後續事務處理,例:總完成時間。

註:以上參考了
SpringCreating Asynchronous Methods 文章。
DZoneSpring Boot: Creating Asynchronous Methods Using @Async Annotation 文章。
程序猿DDSpring Boot中使用@Async实现异步调用 文章。
nealma.comSpring-Boot(十七) Async Of Spring Boot
(十八)SpringBoot2.0使用@Async实现异步调用