首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Java 11 HTTP客户端异步执行

Java 11 HTTP客户端异步执行
EN

Stack Overflow用户
提问于 2018-08-18 10:31:17
回答 2查看 6.4K关注 0票数 21

我正在尝试来自JDK 11的新HTTP客户端API,特别是它执行请求的异步方式。但是有一些事情我不确定我是否理解(某种程度上是实现方面)。在文档中,它说:

在实际情况下,在客户机的CompletableFuture提供的线程上执行异步任务和返回的Executor实例的依赖操作。

正如我所理解的,这意味着如果我在创建HttpClient对象时设置了一个自定义执行器:

代码语言:javascript
运行
复制
ExecutorService executor = Executors.newFixedThreadPool(3);

HttpClient httpClient = HttpClient.newBuilder()
                      .executor(executor)  // custom executor
                      .build();

然后,如果我异步发送请求并在返回的CompletableFuture上添加依赖操作,则依赖操作应该在指定的执行器上执行。

代码语言:javascript
运行
复制
httpClient.sendAsync(request, BodyHandlers.ofString())
          .thenAccept(response -> {
      System.out.println("Thread is: " + Thread.currentThread().getName());
      // do something when the response is received
});

但是,在上面的依赖操作(thenAccept中的使用者)中,我看到执行它的线程来自公共池,而不是自定义执行器,因为它打印Thread is: ForkJoinPool.commonPool-worker-5

这是实现中的错误吗?还是我错过了什么?我注意到它说“实例在客户端的执行器提供的线程上执行,在实际的上执行”,那么这是没有应用的情况吗?

注意,我也尝试过thenAcceptAsync,结果也是一样的。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-08-23 09:51:00

我刚刚找到了一个更新的文档 (我最初链接到的那个看起来很旧),它解释了这个实现行为:

通常,异步任务是在调用操作的线程中执行的,例如,发送是HTTP请求,或者是由客户机的遗嘱执行人提供的线程执行的。不显式指定执行器的依赖任务(由返回的CompletableFuture,或CompletableFutures触发的任务)在与 CompletionStages或调用线程相同的 默认执行器 中执行,如果操作在注册依赖任务之前完成。

CompletableFuture的默认执行器是公共池。

我还找到了引入此行为的错误ID,其中API开发人员对其进行了充分解释:

2)在公共池中运行的依赖任务--依赖任务的默认执行已被更新为与CompletableFuture的defaultExecutor相同的执行器。对于已经使用CF的开发人员来说,这更熟悉,并且减少了HTTP客户端缺乏执行其任务所需的线程的可能性。这只是默认行为,如果需要,HTTP和CompletableFuture都允许更细粒度的控制。

票数 14
EN

Stack Overflow用户

发布于 2018-08-20 13:33:09

短版本:我认为您已经确定了一个实现细节,“在实用的地方”意味着无法保证所提供的executor将被使用。

详细情况:

我已经从这里下载了JDK 11的源代码。(撰写本文时的jdk11-f729ca27cf9a)。

src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java中,有以下类:

代码语言:javascript
运行
复制
/**
 * A DelegatingExecutor is an executor that delegates tasks to
 * a wrapped executor when it detects that the current thread
 * is the SelectorManager thread. If the current thread is not
 * the selector manager thread the given task is executed inline.
 */
final static class DelegatingExecutor implements Executor {

如果executor为true,则该类将使用isInSelectorThread,否则任务将内联执行。这归结为:

代码语言:javascript
运行
复制
boolean isSelectorThread() {
    return Thread.currentThread() == selmgr;
}

其中selmgrSelectorManager编辑:这个类也包含在HttpClientImpl.java

代码语言:javascript
运行
复制
// Main loop for this client's selector
private final static class SelectorManager extends Thread {

结果是:我猜测实际情况意味着它依赖于实现,并且无法保证所提供的executor将被使用。

注意:这与默认的执行器不同,在默认执行器中,构建器不提供executor。在这种情况下,代码显然会创建一个新的缓存线程池。另一种方法是,如果构建器提供了一个executor,则会对SelectorManager进行身份检查。

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51907641

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档