Apache NIO HttpAsyncClient 如何能够等待远程响应而不阻塞任何线程?它是否有办法与操作系统设置回调(我对此表示怀疑?)。否则它会执行某种轮询吗?
编辑 - 这个答案是错误的。不正确请忽略。
您没有指定版本,所以我无法向您指出源代码。但要回答你的问题,Apache 的做法是返回一个
Future<T>
。
注意包装中的链接如何显示
nio
。这代表“非阻塞IO”。十分之九是通过使用新线程做一些工作来完成的。
这几乎与您的
第一个问题中的
CompletableFuture<T>
完全相同。长话短说,库在一个新线程中启动该进程(就像 CompletableFuture<T>
一样),将该线程存储到 Future<T>
中,然后允许您使用该 Future<T>
来管理包含您的非阻塞任务。通过这样做,您可以准确决定代码阻塞的时间和位置,从而有可能使您有机会进行一些重大的性能优化。
为了更明确,让我们给出一个伪代码示例。假设我有一个附加到端点的方法。每当到达端点时,就会执行该方法。该方法接受单个参数 ---
userID
。然后,我使用该 userID
执行 2 个操作 --- 获取用户的个人信息,并获取用户的建议内容。我需要这两部分,并且两个请求都不需要等待另一个请求完成才能开始。所以,我所做的就是下面这样。
public StoreFrontPage visitStorePage(int userID)
{
final Future<UserInfo> userInfoFuture = this.fetchUserInfo(userID);
final Future<PageSuggestion> recommendedContentFuture = this.fetchRecommendedContent(userId);
final UserInfo userInfo = userInfoFuture.get();
final PageSuggestion recommendedContent = recommendedContentFuture.get();
return new StoreFrontPage(userInfo, recommendedContent);
}
当我调用
this.fetchUserInfo(userID)
时,我的代码创建一个新线程,开始在该新线程上获取用户信息,但同时让我的主线程继续并启动 this.fetchRecommendedContent(userID)
。 2 次提取并行发生。
但是,我需要这两个结果才能创建我的
StoreFrontPage
。因此,当我决定在获得两次提取的结果之前不能继续继续时,我会在每次提取时调用 Future::get
。这个方法的作用是将新线程合并回我原来的线程。简而言之,它表示“等待您创建的一个线程完成它正在做的事情,然后将结果作为返回值输出”。
为了更明确地回答你的问题,不,这个工具不需要你做任何涉及回调或轮询的事情。它所做的只是给您一个
Future<T>
,并让您决定何时需要阻塞线程以等待 Future<T>
完成。
编辑 - 这个答案是错误的。不正确请忽略。
异步http客户端一启动,就会启动一个或多个线程。其中一些线程将被阻塞等待数据,但它们是客户端内部的,因此用户创建的线程都不会被阻塞。
该机制比每个请求启动一个线程要简单得多:有一种方法可以将许多套接字复用到一个对象(“选择器”)上,并进行阻塞等待以等待任何套接字准备好读取或写入:这这样,(内部)线程被阻塞,但由于它同时处理许多套接字,因此它不会被其中任何一个阻塞。也许这也有助于“无阻塞”的比喻。