ExectuorService 与 CompletableFuture 的关系

Relation between ExectuorService and CompletableFuture

我正在学习多线程,现在对一个主题感到困惑,即 ExecutorService 和 CompletableFuture。

让我总结一下我到目前为止学到的东西。

ExecutorService 是一个 Java 高级线程 API,它有助于管理线程,即两个独立的线程正在执行它们的任务。但是,如果线程是依赖的,那么我们可以使用生产者-消费者模式等等。 这有助于实现并发。由于多个线程可用于 运行 多个任务。

但是在CompletableFuture中,我们称之为async programming/Reactive programming,也是用来完成同样的任务的。即它也可以 运行 多个线程。

但我不明白何时使用哪一个以及它们之间有何不同?它们在哪些用例中完美地结合在一起?

从本质上讲,CompletableFuture 是一种机制,一个线程可以通过该机制了解另一个线程何时完成某事。

所以,一个典型的模型就是这种方法:

 CompletableFuture<Result> doSomething() {
      CompletableFuture<Result> future = new CompletableFuture<>();
        ... arrange to do work in some other thread ...
      return future;
 }

doSomething() 的调用者取回一个对象,它可以使用该对象来确定完成、等待完成、获得执行 'something' 的结果,也许 运行 一些其他工作使用结果。

那么,doSomething() 是如何安排在其他线程中工作的。好吧,一种方法是通过某些 ExecutorService 执行工作。尽管还有很多其他方法可以解决这个问题。无论如何,工作完成后,它将调用 future.complete(someResult) 将 CompletableFuture 设置为具有预期结果的 'completed' 状态。

也许你很困惑,因为我们的来电者可以写

doSomething().thenAcceptAsync((result) -> blahBlah(result));

在这种情况下,doSomething() 会按上述方式进行。完成后,我们想要 运行 另一个操作,也是异步的。因为我们使用了 AcceptAsync,所以这项工作将通过 CompletableFuture 框架已知的 ExecutorService 处理(确切地说,是常见的 ForkJoinPool - 这已记录在案)。

摘要 - 这不是 'choose one or the other'。 ExecutorServices 为其他线程中的 运行 个工作单元提供了方法。 CompletableFutures 提供了了解这些工作单元的完成并对其做出反应的方法。