CompletableFuture可以用于创建非阻塞I / O调用吗?

时间:2018-03-12 12:46:28

标签: java spring java-8

我正在使用CompletableFuture拨打网络服务电话:

CompletableFuture<List<ProductCatalog>> completeableFuture =
    CompletableFuture.supplyAsync(() -> restTemplate.getForEntity(serviceURL, Response.class))
                     .thenApply(responseEntity -> buildResponse(responseEntity.getBody()));

使用上面的代码,我可以看到JVM分配了一个池工作者(onPool-worker-1)线程来调用Web服务,因此它按预期工作:

2018-03-12 10:11:08.402  INFO 14726 --- [nio-9020-exec-1] c.a.m.service.products.config.LogAspect  : Entering in Method :  productsCatalogClass Name :  com.arrow.myarrow.service.products.controller.ProductsControllerArguments :  []Target class : com.arrow.myarrow.service.products.controller.ProductsController
2018-03-12 10:11:43.561  INFO 14726 --- [onPool-worker-1] c.a.m.s.p.s.ProductsCatalogService       : listProductCatalog has top level elements - 8

由于Web服务调用可能非常耗时,因此我使用CompletableFuture.supplyAsync方法来调用Web服务。有人可以回答以下问题:

  • 主线程是否会被解锁并且可以免费获取其他内容?
  • 它真的是非I / O代码吗?
  • 是否会有任何性能影响或优势?

我在Tomcat上运行我的应用程序作为Spring Boot应用程序。使用CompletableFuture背后的主要灵感是当Web服务(第三方系统)关闭时,我的所有传入请求都不会被阻止。由于默认情况下Tomcat有一个大小为200的线程池,如果200个用户正在等待上述调用的响应,系统是否会被阻止,或者与使用上述代码有什么不同?

1 个答案:

答案 0 :(得分:4)

这不是非阻塞I / O.它只是在一个单独的线程中定期阻塞I / O.更糟糕的是,如果您没有明确提供执行者,CompletableFutures将在公共ForkJoinPool中执行,这将很快填满。

如果使用asynchronous servlet和单独的执行程序,则可以在不使用Tomcat工作池的线程的情况下长时间运行操作。但是,这仅在其他请求可以某种方式完成时才有用。如果所有请求都被卸载到自定义执行程序,那么您只需将一个池切换为另一个池。