成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

性能提升!@Async與CompletableFuture優雅應用

開發 前端
如果異步方法不返回任何值,那么就很難知道方法執行時是否發生了異常。我們可以使用 AsyncUncaughtExceptionHandler 實現來捕獲和處理此類異常。

1. 簡介

@Async 和 CompletableFuture 是實現異步處理的強大工具組合。@Async 是Spring框架提供的一個注解,用于標記方法以表明它將在Spring管理的線程池中的另一個線程上異步執行。這使得開發人員能夠在不阻塞主線程的情況下執行耗時的任務,從而提高應用程序的整體性能和響應速度。

CompletableFuture 是Java 8引入的一個強大的類,它代表了一個可能尚未完成的計算的結果。CompletableFuture 提供了豐富的API來支持異步編程模式,如回調、組合操作、錯誤處理等。通過將@Async與CompletableFuture結合使用,可以實現更高效的異步任務處理。

接下來,我們將介紹@Async與CompletableFuture結合的使用。

2. 實戰案例

2.1 @EnableAsync and @Async

Spring 自帶 @EnableAsync 注解,可應用于 @Configuration 類以實現異步行為。@EnableAsync 注解會查找標有 @Async 注解的方法,并在后臺線程池中運行這些方法。

@Async 注解方法在單獨的線程中執行,并返回 CompletableFuture 來保存異步計算的結果。

開啟異步功能

@Configuration
@EnableAsync
public class AsyncConfig {
  @Bean(name = "asyncExecutor")
  public Executor asyncExecutor()  {
    int core = Runtime.getRuntime().availableProcessors() ;
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(core) ;
    executor.setMaxPoolSize(core) ;
    executor.setQueueCapacity(100) ;
    executor.setThreadNamePrefix("PackAsync-") ;
    executor.initialize() ;
    return executor ;
  }
}

如上我們自定義了線程池,該線程池用來執行我們的異步任務。你也可以不用配置,使用系統默認的線程池。

創建異步任務

@Async("asyncExecutor")
public CompletableFuture<EmployeeNames> task() {
  // TODO
}

用 @Async 對方法進行注解,該方法應異步運行。該方法必須是公共的,可以返回值,也可以不返回值。如果返回值,則應使用 Future 接口實現對其進行封裝。

這里指定了使用我們自定義的線程池執行異步任務。

多個異步任務同時執行

CompletableFuture.allOf(
  asyncMethodOne, 
  asyncMethodTwo, 
  asyncMethodThree
).join() ;

要合并多個異步任務的結果,通過使用 join() 方法,這將等待所有異步任務執行完成才會繼續往后執行。

2.2 Rest Controller中調用異步任務

接下來,我們將創建一個 REST API,從三個遠程服務異步獲取數據,當所有三個服務的響應都可用時,再匯總響應。

  • 調用/addresses接口獲取所有地址信息
  • 調用/phones接口獲取所有電話數據
  • 調用/names接口獲取所有姓名
  • 等待以上3個接口都返回結果后再進行處理
  • 匯總所有三個應用程序接口的響應,并生成最終響應發送回客戶端 

遠程接口準備

@RestController
public class EmployeeController {
  @GetMapping("/addresses")
  public EmployeeAddresses addresses() {
    // TODO
  }
  @GetMapping("/phones")
  public EmployeePhone phones() {
    // TODO
  }
  @GetMapping("/names")
  public EmployeeNames names() {
    // TODO
  }
}

我們將通過異步的方式調用上面定義的3個接口。

異步調用REST API

這些服務方法將從遠程應用程序接口或數據庫中提取數據,必須在不同的線程中并行運行,以加快處理速度。

@Service
public class AsyncService {
  private static Logger logger = LoggerFactory.getLogger(AsyncService.class);
  private final RestTemplate restTemplate;
  public AsyncService(RestTemplate restTemplate) {
    this.restTemplate = restTemplate ;
  }
  @Async("asyncExecutor")
  public CompletableFuture<EmployeeNames> names()  {
    logger.info("getEmployeeName starts");
    EmployeeNames employeeNameData = restTemplate.getForObject("http://localhost:8080/names", EmployeeNames.class) ;
    logger.info("employeeNameData, {}", employeeNameData) ;
    logger.info("employeeNameData completed");
    return CompletableFuture.completedFuture(employeeNameData);
  }
  @Async("asyncExecutor")
  public CompletableFuture<EmployeeAddresses> addresses() {
    logger.info("getEmployeeAddress starts");
    EmployeeAddresses employeeAddressData = restTemplate.getForObject("http://localhost:8080/addresses", EmployeeAddresses.class);
    logger.info("employeeAddressData, {}", employeeAddressData) ;
    logger.info("employeeAddressData completed");
    return CompletableFuture.completedFuture(employeeAddressData);
  }
  @Async("asyncExecutor")
  public CompletableFuture<EmployeePhone> phones() {
    logger.info("getEmployeePhone starts") ;
    EmployeePhone employeePhoneData = restTemplate.getForObject("http://localhost:8080/phones", EmployeePhone.class) ;
    logger.info("employeePhoneData, {}", employeePhoneData) ;
    logger.info("employeePhoneData completed") ;
    return CompletableFuture.completedFuture(employeePhoneData) ;
  }
}

注意:你可不能如下方式來執行遠程接口的調用。

CompletableFuture.supplyAsync(() -> {
  return restTemplate.getForObject("http://localhost:8080/phones", EmployeePhone.class) ;
}) ;

如果你這樣寫,你的遠程接口并非在你的異步線程中執行,而是在CompletableFuturue的線程池中執行(ForkJoinPool)。

2.3 聚合異步任務

接下來在REST API中調用上面的異步方法、消耗和聚合其響應并返回客戶端。

@RestController
public class AsyncController {
  private final AsyncService asyncService;
  public AsyncController(AsyncService service) {
    this.asyncService = asyncService ;
  }


  @GettMapping("/profile/infos")
  public EmployeeDTO infos() throws Exception {
    CompletableFuture<EmployeeAddresses> addresses = asyncService.addresses() ;
    CompletableFuture<EmployeeNames> names = asyncService.names() ;
    CompletableFuture<EmployeePhone> phones = asyncService.phones() ;
    // 等待所有異步任務都執行完成
    CompletableFuture.allOf(addresses, names, phones).join() ;
    return new EmployeeDTO(addresses.get(), names.get(), phones.get()) ;
  }
}

整個請求的耗時將會是請求最長REST API調用所用的時間,這大大提升該接口的性能。

2.4 異常處理

當方法的返回類型是 Future 時,Future.get() 方法會拋出異常,我們應該在聚合結果之前使用 try-catch 塊捕獲并處理異常。

問題是,如果異步方法不返回任何值,那么就很難知道方法執行時是否發生了異常。我們可以使用 AsyncUncaughtExceptionHandler 實現來捕獲和處理此類異常。

@Configuration
public class AsyncConfig implements AsyncConfigurer {


  @Override
  public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
    return new AsyncExceptionHandler() ;
  }


  public class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
    private final Logger logger = LoggerFactory.getLogger(AsyncExceptionHandler.class);
    @Override
    public void handleUncaughtException(Throwable ex, Method method, Object... params) {
      logger.error("Unexpected asynchronous exception at : "
        + method.getDeclaringClass().getName() + "." + method.getName(), ex);
    }
  }
}

責任編輯:武曉燕 來源: Spring全家桶實戰案例源碼
相關推薦

2024-08-06 09:43:54

Java 8工具編程

2024-09-14 11:31:27

@AsyncSpring異步

2024-08-30 09:53:17

Java 8編程集成

2018-09-18 16:20:08

Asyncjavascript前端

2023-11-06 08:01:09

Go同步異步

2023-04-09 16:34:49

JavaSemaphore開發

2024-09-19 08:09:37

MySQL索引數據庫

2009-08-25 15:35:45

citrxinetscalerncore

2011-10-17 09:47:53

應用性能工作負載服務器

2023-08-31 19:17:23

2020-10-27 08:24:01

Java

2018-12-10 15:13:06

緩存系統性能數據

2015-01-21 15:40:44

GoRuby

2022-11-27 08:12:11

RocketMQ源碼工具類

2012-09-04 09:18:02

NPBBYOD

2011-09-20 10:41:45

Web

2013-12-02 17:33:52

Radware

2009-06-26 14:13:38

OSCache

2010-01-21 23:29:06

戴爾銀行東亞銀行

2023-11-06 09:32:52

Java實踐
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美亚洲国产日韩 | 欧美日韩高清在线一区 | 久久精片| 美女国内精品自产拍在线播放 | 理论片午午伦夜理片影院 | 天天影视综合 | 日韩欧美三级电影在线观看 | 五月婷婷视频 | 成人久久久 | 欧美性猛交一区二区三区精品 | 福利片在线| avtt国产 | 午夜影院在线视频 | 国产精品免费视频一区 | 91麻豆精品国产91久久久更新资源速度超快 | 99re热这里只有精品视频 | 精品久久久久久亚洲综合网站 | 91一区二区三区 | 久久久涩 | 久久99精品久久久久久国产越南 | 69视频在线播放 | 免费国产一区二区 | 欧美黄色片在线观看 | 自拍视频网站 | 欧美日韩一区二区在线观看 | 亚洲手机视频在线 | 91在线资源| 国产久| 欧美成人专区 | 亚洲国产aⅴ成人精品无吗 国产精品永久在线观看 | 在线只有精品 | 日韩日韩日韩日韩日韩日韩日韩 | 亚洲视频一区在线 | 日韩精品免费在线 | 成人黄色三级毛片 | 亚洲欧洲精品成人久久奇米网 | 国产精品久久久久久久久久久久久 | 天天拍天天操 | 日韩久久精品 | 欧美一区两区 | 亚洲精品在线免费 |