当前位置: 首页 > 知识库问答 >
问题:

在设计异步Java API时,如何确保整个CompletableFuture链由内部线程池执行?

贺子昂
2023-03-14

我正在编写一个库,该库提供了几个返回“可完成未来”的异步方法。该库具有一个内部线程池,用于执行异步方法的计算工作。

我想确保满足以下两个要求:

  1. 返回的“可完成未来”不是由内部线程完成的,因此我的库外部的“可完成未来”链永远不会被库的内部线程池执行
  2. 我的异步方法的所有计算都由内部线程池执行,而不是由用户线程(即方法调用方的线程)执行

所以说图书馆有以下阻止方法

Data request(Address address) {
  Message request = encode(address);
  Message response = sendAndReceive(request);
  Data responseData = decode(response);
  return responseData;
}

和相应的异步方法

  CompletableFuture<Data> requestAsync(Address address) {
    return CompletableFuture.supplyAsync(() -> encode(address), internalThreadPool)
        .thenCompose(request -> sendAndReceiveAsync(request))
        .thenApply(response -> decode(response));
  }

第一个要求是通过添加链接来满足的。当完成同步((v,t) -

但是,为了满足第二个要求,需要做些什么呢?


共有1个答案

冯元魁
2023-03-14

Sergey Kuksenko在这里讨论了第二个需求的解决方案,并已在Java11的HttpClient实现中实现。

不满足要求,因为不能保证decode(响应)由内部线程执行。如果encode和sendAndReceiveAsync快速完成,decode实际上可以由调用者的线程执行。

可以通过引入CompletableFuturestartCf来启动CF链来解决该问题。

因此,完整的解决方案可能如下所示

CompletableFuture<Data> requestAsyncFixedAll(Address address) {
  CompletableFuture<Void> startCf = new CompletableFuture<>();
  CompletableFuture<Data> dataCf =  startCf.thenApplyAsync(v -> encode(address), internalThreadPool)
    .thenCompose(request -> sendAndReceiveAsync(request))
    .thenApply(response -> decode(response)).whenCompleteAsync((v, t) -> {});
  startCf.complete(null);
  return dataCf;
}
 类似资料:
  • 我知道使用无线程异步有更多线程可用于服务输入(例如HTTP请求),但我不明白当异步操作完成并且需要一个线程来运行它们的延续时,这如何不可能导致线程饥饿。 假设我们只有3个线程 并且它们在需要线程的长时间运行的操作中被阻塞(例如在单独的db服务器上进行数据库查询) 使用async Wait,您可以 然而,在我看来,这可能会导致“正在进行”的异步操作过剩,如果太多的操作同时完成,那么就没有线程可以运行

  • 我需要执行一些任务。有些任务是独立的,有些任务依赖于其他任务的成功执行。独立任务可以并行运行以获得更好的性能。我把这些任务称为服务。列说明哪些服务将以串联方式执行,哪些服务将以并联方式执行。列描述了一组定义的服务所遵循的执行顺序。例如,服务A和B应该并行运行。如果它们已成功执行,则将执行服务C。请注意,服务C并不直接依赖于其先前服务的输出,但它必须在成功执行其先前服务后运行,因为服务C在执行期间需

  • 问题内容: 在Java中拥有多个线程池的优缺点是什么?我已经看过代码,其中有多个线程池用于不同的“类型”任务,而且我不确定它是更好的设计还是只是开发人员感到懒惰。一个示例是将ScheduledThreadPoolExecutor用于定期执行的任务或具有超时的任务,而将另一ThreadPoolExecutor用于其他任务。 问题答案: 具有单独的专用线程池的目的是,使活动不会因线程不足而被饥饿,因为

  • 一、组件介绍(怎么确保得到a3) 1、组件内有a1,a2,用来接收父组件的传值,需要通过a1,a2来得到一个 a3 2、父组件在使用时a1,a2的来源是通过两个不同的api获取的,a1,a2都是异步的 二、解决方案(目前的方案) 1、前提条件如下:(1)它是组件,尽量是不去要求父组件去控制api请求顺序,比如async await控制两个请求的顺序(2)a1,a2的来源是可能随时变的,可能通过一个

  • 问题内容: 我决定使自己熟悉node.js,并阅读有关该主题的几篇文章。我仍然不清楚的是,当您调用node.js函数时,node.js是否在线程池中创建新线程和/或在线程上调度任务。 例如,如果我调用它是否在其他线程上执行? 如果是,[如何]我可以编写自己的函数或在其他线程上运行? 问题答案: 没有用于文件操作的异步API,因此node.js为此使用了线程池。您可以在libuv的代码中看到它。 该

  • 问题内容: 如果我在同步块内创建一个新线程,该块是否将保持锁定状态,直到线程执行完成为止?如果没有,那么直到什么时候才能保持锁定状态? 问题答案: 如果代码d具有新创建的线程,则它将保持锁定,从而等待它完成。由于没有锁,因此在调用完成后将不释放锁定。