代码之家  ›  专栏  ›  技术社区  ›  M A

Java 11 HTTP客户端异步执行

  •  11
  • M A  · 技术社区  · 6 年前

    我正在尝试JDK 11中的新HTTP客户端API,特别是它执行请求的异步方式。但有些东西我不确定我是否理解(某种实现方面)。在 documentation

    返回的异步任务和依赖操作 CompletableFuture 实例在客户端提供的线程上执行 Executor ,如果可行。

    据我所知,这意味着如果在创建 HttpClient

    ExecutorService executor = Executors.newFixedThreadPool(3);
    
    HttpClient httpClient = HttpClient.newBuilder()
                          .executor(executor)  // custom executor
                          .build();
    

    然后,如果我异步发送请求并在返回的 完全未来

    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 .

    这是实现中的一个bug吗?或者我遗漏了什么?我注意到上面写着“实例在客户端执行器提供的线程上执行, “,那么这是不适用的情况吗?

    注意我也试过 thenAcceptAsync 同样的结果。

    2 回复  |  直到 6 年前
        1
  •  10
  •   M A    6 年前

    我刚找到一个更新的 documentation (我最初链接到的那个似乎很旧)它解释了这个实现行为:

    sending 一个HTTP请求,或者由客户机的 executor 依赖任务,那些由返回的CompletionStages或CompletableFutures触发的任务,它们没有显式指定执行器,在同一时间执行 default executor 作为 CompletableFuture

    以及 完全未来

    我还发现了 bug ID 这就引入了这种行为,在这种行为中,API开发人员完全解释了它:

    依赖任务的默认执行已更新为与CompletableFuture的defaultExecutor在同一个执行器中运行。这对于已经使用CF的开发人员来说更为熟悉,并降低了HTTP客户机执行其任务时缺少线程的可能性。这只是默认行为,如果需要,HTTP客户端和CompletableFuture都允许更精细的粒度控制。

        2
  •  8
  •   Michael Easter    6 年前

    简短版本:我认为您已经确定了一个实现细节 “意思是不能保证 executor 将被使用。

    我已经从 here jdk11-f729ca27cf9a 在撰写本文时)。

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

    /**
     * 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 {
    

    这个类使用 如果 isInSelectorThread 为true,否则任务以内联方式执行。这可以归结为:

    boolean isSelectorThread() {
        return Thread.currentThread() == selmgr;
    }
    

    selmgr 是一个 SelectorManager 编辑 :此类还包含在 HttpClientImpl.java

    // Main loop for this client's selector
    private final static class SelectorManager extends Thread {
    

    结果是:我猜 如果可行 执行人 将被使用。

    执行人 执行人 ,的身份检查 选择器管理器