首页 > 解决方案 > ExecutorService vs CompletableFuture

问题描述

我一直在尝试实现一个异步过程,其中父方法调用一个子方法,该子方法又会调用三种不同的方法。我希望所有这些过程都异步完成,即在子方法中的这三个调用并行进行之后,控件应该返回父方法并继续执行其余部分。

我有这段代码,经过测试可以正常工作。

public ReturnSomething parent(){
    child();
    ...//rest to UI
}

private void child(){
  ExecutorService executorService = Executors.newFixedThreadPool(3);

  Runnable service1 = () -> {
     MyFileService.service1();
  };

  Runnable service2 = () -> {
      MyFileService.service2();
  };

  Runnable service3 = () -> {
      MyFileService.service3();
  };

  executorService.submit(service1);
  executorService.submit(service2);
  executorService.submit(service3);
}

现在,我的领导要求我改用这个。

public ReturnSomething parent(){
    child();
    ...//rest to UI
}

private void child(){
    CompletableFuture.supplyAsync(() ->  MyFileService.service1();
    CompletableFuture.supplyAsync(() ->  MyFileService.service2();
    CompletableFuture.supplyAsync(() ->  MyFileService.service3();
}

我知道 CompletableFuture 是 Java 8 的新功能,但是第二个代码比第一个代码更好吗?因为对于 ExecutorService,我没有调用“get()”方法,所以我不会等待 aysnc 响应。那么,有人可以解释一下有什么区别吗?

标签: javaasynchronousjava-8executorservicecompletable-future

解决方案


在功能上,这两种方法或多或少是相同的:

  • 您提交任务以供执行;
  • 你不等待结果。

但是,从技术上讲,存在一些细微的差异:

  • 在第二种方法中,您没有指定执行程序,因此它将使用 common ForkJoinPoolsupplyAsync()如果您不想这样做,则必须传递执行者作为第二个参数;
  • CompletableFutureAPI 允许轻松链接更多调用thenApply()thenCompose()等等。因此它比简单Future返回的更灵活ExecutorService.submit()
  • UsingCompletableFuture允许child()使用return CompletableFuture.allOf(the previously created futures).

关于可读性,这是一个偏好问题,但如果你想要等效的代码,CompletableFuture一旦你对它进行了类似的格式化,这种方法可能会被认为可读性较差。相比:

executorService.submit(MyFileService::service1);
executorService.submit(MyFileService::service2);
executorService.submit(MyFileService::service3);

CompletableFuture.supplyAsync(MyFileService::service1, executorService);
CompletableFuture.supplyAsync(MyFileService::service2, executorService);
CompletableFuture.supplyAsync(MyFileService::service3, executorService);

推荐阅读