考虑一下代码:
@Autowired
private AsyncRestOperations restTemplate;
@RequestMapping("/abcd")
public CompletableFuture<Result> process(HttpRequest request) {
convertListenableFutureToCompletableFuture(restTemplate.getForEntity("http://...", Result.class))
.thenApply(/*Some logic here*/)
.thenCompose(/*Some logic returns future*/)
}
在这里,我可以看到以下处理顺序:
DispatcherServlet
的请求。DispatcherServlet
确定处理程序并向其传递请求。process
方法被调用restTemplate.getForEntity
被召唤。thenApply
被称为thenCompose
被称为DispatcherServlet
(或其他Spring组件)据我所知,点1-3
和7
在同一个线程池中执行(我是对吗?)。
但是用什么线程(池)来执行点4-6
?
答案 0 :(得分:2)
1-3&amp; 7在同一个线程上执行(调用4)
5,6在相同的线程上执行,这是提供CompletableFuture结果的相同线程(在步骤4中,很可能不是用于相同的线程)调用restTemplate)。
AsyncRestOperations是一个接口,因此内部发生的事情取决于底层实现。
如果您使用的是NIO Rest Client,则会在NIO客户端的内部事件循环池中执行Rest调用(5&amp; 6也可能不是您想要的 - 请参阅thenApplyAsync,然后是thenCompose)。
您正在使用Async Blocking I / O Rest客户端&amp;通常,调用将在其配置的线程池中的线程上执行 - 遗憾的是,您正在使用的类的默认行为不是配置线程池,而是每次使用新线程 - 见下文 - (5&amp; 6在这里执行相同的线程可能很好,甚至是最优的。)
更新
基于进一步的信息:该示例使用AsyncRestTemplate
Spring的异步客户端HTTP访问的中心类。 ...
注意:默认情况下,AsyncRestTemplate依赖于标准的JDK工具 建立HTTP连接。您可以切换为使用其他HTTP Apache HttpComponents,Netty和OkHttp等库通过使用 接受AsyncClientHttpRequestFactory的构造函数。
AsyncRestTemplate使用Spring的SimpleAsyncTaskExecutor(当通过默认构造函数实例化时)
TaskExecutor实现,为每个任务激活一个新线程, 异步执行它。支持限制并发线程 通过&#34; concurrencyLimit&#34;豆类财产。默认情况下,数字 并发线程是无限的。
注意:此实现不会重用线程!考虑一下 相反,线程池TaskExecutor实现,尤其适用于 执行大量短期任务。
后面的部分可能是次优的,我会配置AsyncRestTemplate来使用你自己的线程池。