SpringBoot之——使用@Async實現非同步呼叫
阿新 • • 發佈:2019-02-12
一、什麼是“非同步呼叫”
“非同步呼叫”對應的是“同步呼叫”,同步呼叫指程式按照定義順序依次執行,每一行程式都必須等待上一行程式執行完成之後才能執行;非同步呼叫指程式在順序執行時,不等待非同步呼叫的語句返回結果就執行後面的程式。
二、同步呼叫
下面通過一個簡單示例來直觀的理解什麼是同步呼叫:
定義Task類,建立三個處理函式分別模擬三個執行任務的操作,操作消耗時間隨機取(10秒內)
編寫一個訪問方法:package com.lyz.springboot.task; import java.util.Random; import org.springframework.stereotype.Component; /** * 定義3個任務 * @author liuyazhuang */ @Component publicclass Task1 { //定義一個隨機物件. public static Random random =new Random(); //任務一; public void doTaskOne() throws Exception { System.out.println("開始做任務一"); long start = System.currentTimeMillis(); Thread.sleep(random.nextInt(10000)); long end = System.currentTimeMillis(); System.out.println("完成任務一,耗時:" + (end - start) + "毫秒"); } //任務二; public void doTaskTwo() throws Exception { System.out.println("開始做任務二"); long start = System.currentTimeMillis(); Thread.sleep(random.nextInt(10000)); long end = System.currentTimeMillis(); System.out.println("完成任務二,耗時:" + (end - start) + "毫秒"); } //任務三; public void doTaskThree() throws Exception { System.out.println("開始做任務三"); long start = System.currentTimeMillis(); Thread.sleep(random.nextInt(10000)); long end = System.currentTimeMillis(); System.out.println("完成任務三,耗時:" + (end - start) + "毫秒"); } }
//測試task1.
@RequestMapping("/task1")
public String task1() throws Exception{
task1.doTaskOne();
task1.doTaskTwo();
task1.doTaskThree();
return "task1";
}
執行可以看到類似如下輸出:開始做任務一
完成任務一,耗時:4156毫秒
開始做任務二
完成任務二,耗時:557毫秒
開始做任務三
完成任務三,耗時:6171毫秒
三、非同步呼叫
上述的同步呼叫雖然順利的執行完了三個任務,但是可以看到執行時間比較長,若這三個任務本身之間不存在依賴關係,可以併發執行的話,同步呼叫在執行效率方面就比較差,可以考慮通過非同步呼叫的方式來併發執行。在Spring Boot中,我們只需要通過使用@Async註解就能簡單的將原來的同步函式變為非同步函式,Task類改在為如下模式:
為了讓@Async註解能夠生效,還需要在Spring Boot的主程式中配置@EnableAsync,如下所示:package com.lyz.springboot.task; import java.util.Random; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; /** * 定義3個任務 * @author liuyazhuang */ @Component public class Task2 { //定義一個隨機物件. publicstatic Random random =new Random(); //任務一; @Async public void doTaskOne() throws Exception { System.out.println("開始做任務一"); long start = System.currentTimeMillis(); Thread.sleep(random.nextInt(10000)); long end = System.currentTimeMillis(); System.out.println("完成任務一,耗時:" + (end - start) + "毫秒"); } //任務二; @Async public void doTaskTwo() throws Exception { System.out.println("開始做任務二"); long start = System.currentTimeMillis(); Thread.sleep(random.nextInt(10000)); long end = System.currentTimeMillis(); System.out.println("完成任務二,耗時:" + (end - start) + "毫秒"); } //任務3; @Async public void doTaskThree() throws Exception { System.out.println("開始做任務三"); long start = System.currentTimeMillis(); Thread.sleep(random.nextInt(10000)); long end = System.currentTimeMillis(); System.out.println("完成任務三,耗時:" + (end - start) + "毫秒"); } }
@SpringBootApplication
@EnableAsync
publicclass App {
//省略其它程式碼…
}
編寫測試方法://測試task2.
@RequestMapping("/task2")
public String task2() throws Exception{
task2.doTaskOne();
task2.doTaskTwo();
task2.doTaskThree();
return"task2";
}
此時可以反覆執行單元測試,您可能會遇到各種不同的結果,比如:開始做任務一 開始做任務二 開始做任務三 完成任務三,耗時:57毫秒 完成任務二,耗時:3621毫秒 完成任務一,耗時:7419毫秒