【发布时间】:2019-01-25 05:16:17
【问题描述】:
我正在尝试来自 JDK 11 的新 HTTP 客户端 API,特别是它执行请求的异步方式。但是有些东西我不确定我是否理解(某种实现方面)。在documentation 中,它说:
返回的
CompletableFuture实例的异步任务和相关操作在可行的情况下在客户端Executor提供的线程上执行。
据我了解,这意味着如果我在创建HttpClient 对象时设置了自定义执行器:
ExecutorService executor = Executors.newFixedThreadPool(3);
HttpClient httpClient = HttpClient.newBuilder()
.executor(executor) // custom executor
.build();
那么如果我异步发送请求并在返回的CompletableFuture 上添加依赖操作,则依赖操作应该在指定的执行器上执行。
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,结果相同。
【问题讨论】:
-
对不起,如果这很愚蠢,但请帮助我理解,您是如何解释 它来自公共池而不是自定义执行器,因为它打印线程是:ForkJoinPool.commonPool-worker-5 ?...我还在
thenAccept消费者中尝试了System.out.println(httpClient.executor().get().equals(executor));,它打印出true。 -
@nullpointer 我假设他在
thenAcceptConsumer中打印出Thread.currentThread().getName()并且名称表明Thread来自常见的ForkJoinPool,而不是自定义的Executor.换句话说,OP 并不是说HttpClient的Executor发生了更改,OP 想知道为什么依赖的CompletableFuture阶段是使用不同的线程池执行的。 -
@nullpointer 正是 Slaw 所说的。我也知道线程来自公共池,因为我可以给自定义执行器创建的线程特殊名称以清楚地识别它们。至于
httpClient.executor(),这个方法只是返回我创建时指定的执行器,不是thenAccept使用的。 -
@Slaw @manouti 谢谢。我得到了你们俩所指的内容,确实尝试向执行程序提供一个自定义命名线程,并且可以看到它没有在
thenAccept中使用。将进一步寻找有关实用部分的详细信息以及错误数据库。 -
原来在这个 API 的过程中文档已经被更新了,所以它描述了这个行为。最新的文档链接是 download.java.net/java/early_access/jdk11/docs/api/…
标签: java http asynchronous completable-future java-11