中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

SpringBoot怎么優雅地實現異步調用

發布時間:2023-03-17 11:31:13 來源:億速云 閱讀:126 作者:iii 欄目:開發技術

這篇文章主要講解了“SpringBoot怎么優雅地實現異步調用”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“SpringBoot怎么優雅地實現異步調用”吧!

前言

  • 同步編程:在同步編程中,任務一次執行一個,只有當一個任務完成時,下一個任務才會被解除阻塞。

  • 異步編程:在異步編程中,可以同時執行多個任務。您可以在上一個任務完成之前轉到另一個任務。

SpringBoot怎么優雅地實現異步調用

Spring Boot中,我們可以使用@Async注解來實現異步行為。

實現步驟

1.定義一個異步服務接口AsyncService.java

public interface AsyncService {

    void asyncMethod() throws InterruptedException;

    Future<String> futureMethod() throws InterruptedException;
}

2.實現定義的接口AsyncServiceImpl.java

@Service
@Slf4j
public class AsyncServiceImpl implements AsyncService  {

    @Async
    @Override
    public void asyncMethod() throws InterruptedException {
        Thread.sleep(3000);
        log.info("Thread: [{}], Calling other service..", Thread.currentThread().getName());
    }

    @Async
    @Override
    public Future<String> futureMethod() throws InterruptedException {
        Thread.sleep(5000);
        log.info("Thread: [{}], Calling other service..", Thread.currentThread().getName());
        return new AsyncResult<>("task Done");
    }
}
  • AsyncServiceImpl 是一個 spring 管理的 bean

  • 您的異步方法必須是公共的,而且是被@Async注解修飾。

  • 返回類型被限制為 void 或 Future

3.定義一個控制器AsyncController.java

@EnableAsync
@RestController
@Slf4j
public class AsyncController {
    @Autowired
    AsyncService asyncService;

    @GetMapping("/async")
    public String asyncCallerMethod() throws InterruptedException {
        long start = System.currentTimeMillis();
        log.info("call async method, thread name: [{}]", Thread.currentThread().getName());
        asyncService.asyncMethod();
        String response = "task completes in :" +
                (System.currentTimeMillis() - start) + "milliseconds";
        return response;
    }

    @GetMapping("/asyncFuture")
    public String asyncFuture() throws InterruptedException, ExecutionException {
        long start = System.currentTimeMillis();
        log.info("call async method, thread name: [{}]", Thread.currentThread().getName());
        Future<String> future = asyncService.futureMethod();
        // 阻塞獲取結果
        String taskResult = future.get();
        String response = taskResult + "task completes in :" +
                (System.currentTimeMillis() - start) + "milliseconds";
        return response;
    }
}
  • 關鍵點,需要添加啟用異步的注解@EnableAsync ,當然這個注解加在其他地方也ok得。

  • 當外部調用該接口時,asyncMethod()將由默認任務執行程序創建的另一個線程執行,主線程不需要等待完成異步方法執行。

4.運行一下

現在我們運行一下看看,是不是異步返回的。

SpringBoot怎么優雅地實現異步調用

SpringBoot怎么優雅地實現異步調用

可以看到調用/async接口,最終一步調用了方法。

SpringBoot怎么優雅地實現異步調用

SpringBoot怎么優雅地實現異步調用

調用/asyncFuture,發現返回5秒多,難道不是異步的嗎?其實也是異步的,看日志可以看出來,只不過我們返回的是Future,調用Futrue.get()是阻塞的。

自定義異步任務執行器和異常處理

我們現在看看如果異常方法中報錯了會怎么樣?修改異步代碼如下所示,會拋運行時異常:

SpringBoot怎么優雅地實現異步調用

再次執行異步接口,如下所示,會使用默認的線程池和異常處理。

SpringBoot怎么優雅地實現異步調用

我們也可以自定義異步方法的處理異常和異步任務執行器,我們需要配置 AsyncUncaughtExceptionHandler,如下代碼所示:

@Configuration
public class AsynConfiguration extends AsyncConfigurerSupport {
   @Override
   public Executor getAsyncExecutor() {
      ThreadPoolTaskExecutor executor = new 
                ThreadPoolTaskExecutor();
      executor.setCorePoolSize(3);
      executor.setMaxPoolSize(4);
      executor.setThreadNamePrefix("asyn-task-thread-");
      executor.setWaitForTasksToCompleteOnShutdown(true);
      executor.initialize();
      return executor;
  }
  @Override
  public AsyncUncaughtExceptionHandler  
         getAsyncUncaughtExceptionHandler() {
     return new AsyncUncaughtExceptionHandler() {
   
        @Override
        public void handleUncaughtException(Throwable ex, 
           Method method, Object... params) {
           System.out.println("Exception: " + ex.getMessage());
           System.out.println("Method Name: " + method.getName());
           ex.printStackTrace();
        }
    };
  }
}

再次運行,得到的結果如下:

SpringBoot怎么優雅地實現異步調用

@Async如何工作的

必須通過使用 @EnableAsync注解注解主應用程序類或任何直接或間接異步方法調用程序類來啟用異步支持。主要通過代理模式實現,默認模式是 Proxy,另一種是 AspectJ。代理模式只允許通過代理攔截調用。永遠不要從定義它的同一個類調用異步方法,它不會起作用。

當使用 @Async對方法進行注解時,它會根據“proxyTargetClass”屬性為該對象創建一個代理。當 spring 執行這個方法時,默認情況下它會搜索關聯的線程池定義。上下文中唯一的 spring 框架 TaskExecutor bean 或名為“taskExecutor”的 Executor bean。如果這兩者都不可解析,默認會使用spring框架SimpleAsyncTaskExecutor來處理異步方法的執行。

感謝各位的閱讀,以上就是“SpringBoot怎么優雅地實現異步調用”的內容了,經過本文的學習后,相信大家對SpringBoot怎么優雅地實現異步調用這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

壤塘县| 上犹县| 阿坝| 望奎县| 如东县| 山阳县| 波密县| 建瓯市| 长岛县| 扶绥县| 呼和浩特市| 合水县| 辽阳县| 仁化县| 定结县| 安新县| 东宁县| 濮阳市| 抚州市| 始兴县| 伊川县| 巴东县| 安化县| 秭归县| 随州市| 通化县| 东丽区| 万源市| 安仁县| 河曲县| 高雄市| 连平县| 义乌市| 赤壁市| 苏州市| 盐源县| 蛟河市| 宾川县| 怀柔区| 精河县| 德安县|