线程池如何"映射"对于未来春季的执行?

时间:2015-09-24 11:09:47

标签: java multithreading spring spring-mvc asynchronous

考虑一下代码:

@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*/)
}

在这里,我可以看到以下处理顺序:

  1. Spring收到DispatcherServlet的请求。
  2. DispatcherServlet确定处理程序并向其传递请求。
  3. process方法被调用
  4. restTemplate.getForEntity被召唤。
  5. thenApply被称为
  6. thenCompose被称为
  7. CompletableFuture&#34;返回&#34;回到DispatcherServlet(或其他Spring组件)
  8. 据我所知,点1-37在同一个线程池中执行(我是对吗?)。

    但是用什么线程(池)来执行点4-6

1 个答案:

答案 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来使用你自己的线程池。