CompletableFuture.supplyAsync 和 ExecutorService.submit 的区别

发布时间:2024年01月24日
  1. 返回类型:

    • CompletableFuture.supplyAsync 返回一个 CompletableFuture,它允许你链式地组合多个异步操作,并提供更丰富的异步编程接口。
    • ExecutorService.submit 返回一个 Future,它相对简单,只能获取异步任务的结果。
  2. 异步编程接口:

    • CompletableFuture 提供了更强大的异步编程接口,例如 thenApplythenAcceptthenCompose 等,允许你在一个异步任务完成后执行另一个异步任务。
    • Future 的接口相对较简单,主要提供 get 方法用于获取异步任务的结果。
  3. 异常处理:

    • CompletableFuture 具有更灵活的异常处理机制,可以通过 exceptionally 方法捕获异步任务的异常。
    • Future 的异常处理相对较为有限。
  4. 依赖关系:

    • CompletableFuture 允许你构建多个异步任务之间的依赖关系,通过 thenApplythenCombine 等方法,可以在一个任务完成后执行下一个任务。
    • Future 需要通过 get 阻塞等待任务完成,无法方便地构建依赖关系。
  5. Executor 的选择:

    • CompletableFuture.supplyAsync 默认使用 ForkJoinPool 进行异步执行,也可以通过重载方法指定其他 Executor
    • ExecutorService.submit 需要显式传递一个 Executor
      // CompletableFuture 示例
      CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
          // 异步计算的逻辑
          return "Hello, CompletableFuture!";
      });
      
      // 在这里可以执行其他操作
      
      // 获取异步计算的结果
      String result = future.join();
      System.out.println(result);
      
      // ExecutorService.submit 示例
      ExecutorService executorService = Executors.newFixedThreadPool(5);
      
      Future<String> future = executorService.submit(() -> {
          // 异步计算的逻辑
          return "Hello, ExecutorService.submit!";
      });
      
      // 在这里可以执行其他操作
      
      // 获取异步计算的结果
      String result = future.get();
      System.out.println(result);
      
      // 记得关闭线程池
      executorService.shutdown();
      

      接下来给大家展示一个更通用的CompletableFuture.supplyAsync 的模版

      @Override
      public Map<Long, List<Integer>> queryTechIdsMapByDealProductIds(List<Long> productIds) {
          // 创建一个并发安全的 Map,用于存储查询结果,其中 key 为产品ID,value 为技师ID列表
          Map<Long, List<Integer>> techMap = Maps.newConcurrentMap();
      
          // 使用 Stream 对产品ID列表进行处理
          productIds.stream()
                  .filter(Objects::nonNull) // 过滤掉为空的产品ID
                  .map(productId -> {
                      // 使用 CompletableFuture 实现异步查询技师ID
                      return CompletableFuture.supplyAsync(() ->
                                      // 异步调用 queryShowTechnicianIdByGoods 方法,返回技师ID列表
                                      techGoodsBindService.queryShowTechnicianIdByGoods(productId.intValue(), TechGoodBindEnum.GROUP),
                              executorService) // 使用指定的 executorService 处理异步任务
                              .thenAccept(result -> techMap.put(productId, result)) // 将查询结果放入 techMap
                              .exceptionally(e -> {
                                  // 异常处理,记录错误日志
                                  log.error("queryTechIdsByDealProductId 异常, productId={}", productId, e);
                                  return null;
                              });
                  })
                  .collect(Collectors.toList()) // 收集 CompletableFuture 到列表中
                  .forEach(CompletableFuture::join); // 等待所有异步任务完成
      
          // 返回查询结果的 Map
          return techMap;
      }
      

      总体而言,CompletableFuture 提供了更强大和灵活的异步编程功能,适用于构建复杂的异步任务链。ExecutorService.submit 则是一个更底层和简单的异步执行方式,适用于基本的异步任务执行。选择取决于具体的需求和异步编程的复杂性。

文章来源:https://blog.csdn.net/weixin_43873239/article/details/135785187
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。