[英]Java 11 HTTP client asynchronous execution
我正在尝试JDK 11中的新HTTP客户端API,特别是它执行请求的异步方式。 但有些事情我不确定我理解(有点像实现方面)。 在文档中 ,它说:
在可行的情况下,返回的
CompletableFuture
实例的异步任务和相关操作将在客户端的Executor
提供的线程上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
中的thenAccept
)中,我看到执行它的线程来自公共池而不是自定义执行器,因为它打印的Thread is: ForkJoinPool.commonPool-worker-5
。
这是实施中的错误吗? 或者我错过了什么? 我注意到它说“实例是在客户端的执行程序提供的线程上执行的, 在实际可行的情况下”,这是不适用的情况?
请注意,我也尝试了thenAcceptAsync
,它也是相同的结果。
我刚刚发现了一个更新的文档 (我最初链接的文档似乎很旧),它解释了这个实现行为:
通常,异步任务在调用操作的线程中执行,例如发送 HTTP请求,或者由客户端执行程序提供的线程执行 。 相关任务,由返回的CompletionStages或CompletableFutures触发的未明确指定执行程序的任务,在与
CompletableFuture
相同的默认执行程序中执行 ,或者如果操作在注册相关任务之前完成,则执行调用线程。
CompletableFuture
的默认执行程序是公共池。
我还发现了引入此行为的错误ID ,其中API开发人员完全解释了这一点:
2)在公共池中运行的相关任务已更新从属任务的默认执行,以在与CompletableFuture的defaultExecutor相同的执行程序中运行。 对于已经使用CF的开发人员来说,这更为熟悉,并降低了HTTP客户端缺乏执行其任务的线程的可能性。 这只是默认行为,如果需要,HTTP Client和CompletableFuture都允许更细粒度的控制。
简短版本:我认为您已经确定了一个实现细节,“ 实际可行 ”意味着不能保证将使用提供的executor
。
详细地:
我从这里下载了JDK 11源代码。 ( jdk11-f729ca27cf9a
时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,则isInSelectorThread
使用executor
isInSelectorThread
,否则任务将isInSelectorThread
联方式执行。 这归结为:
boolean isSelectorThread() {
return Thread.currentThread() == selmgr;
}
其中selmgr
是SelectorManager
。 编辑 :此类也包含在HttpClientImpl.java
:
// Main loop for this client's selector
private final static class SelectorManager extends Thread {
结果:我猜测实际意味着它是依赖于实现的,并且不能保证将使用提供的executor
。
注意:这与默认执行程序不同,其中构建器不提供executor
。 在这种情况下,代码清楚地创建了一个新的缓存线程池。 换句话说,如果构建器提供executor
,则会进行SelectorManager
的标识检查。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.