Java 线程池是怎样的;“映射”;将来春天执行死刑?
考虑一个代码:Java 线程池是怎样的;“映射”;将来春天执行死刑?,java,multithreading,spring,spring-mvc,asynchronous,Java,Multithreading,Spring,Spring Mvc,Asynchronous,考虑一个代码: @Autowired private AsyncRestOperations restTemplate; @RequestMapping("/abcd") public CompletableFuture<Result> process(HttpRequest request) { convertListenableFutureToCompletableFuture(restTemplate.getForEntity("http://...", Result
@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*/)
}
@Autowired
私有异步REST操作restTemplate;
@请求映射(“/abcd”)
公共CompletableFuture进程(HttpRequest请求){
ConvertListenableFutureTompleFuture(restTemplate.getForEntity(“http://...“,Result.class”)
.然后应用(/*此处有一些逻辑*/)
.thenCompose(/*某些逻辑返回future*/)
}
在这里,我可以看到以下处理顺序:
DispatcherServlet
确定处理程序并将请求传递给它然后调用apply
然后调用compose
1-3
和7
是在同一线程池中执行的(对吗?)
但是使用什么线程(池)来执行点4-6
?- 1-3和7在同一线程上执行(调用4也是如此)
- 5,6在彼此相同的线程上执行,这是提供可完成的未来结果的同一线程(在步骤4中,很可能不是用于调用restTemplate的同一线程)
- AsyncRestOperations是一个接口,因此内部发生的事情将取决于底层实现
- 如果您使用的是NIO Rest客户机,Rest调用将在NIO客户机的内部事件循环池上执行(如5和6,这可能不是您想要的-请参阅ApplySync,然后是Compose)
- 您使用的是异步阻塞I/O Rest客户端&通常调用将在其配置的线程池中的线程上执行-不幸的是,您使用的类的默认行为不是配置线程池,而是每次使用新线程-请参阅下文-(这里在同一个线程上执行5和6可能很好,甚至是最佳的)
注意:此实现不重用线程!请考虑 线程池TaskExecutor实现,尤其是 执行大量短期任务
后面的部分可能是次优的,我会将AsyncRestTemplate配置为使用您自己的线程池。如果您发布RESTTemplatebean的配置(我们只能看到接口定义)调用步骤4后,应该可以准确地告诉您发生了什么。它只是SpringRESTAsync模板,它是这样创建的
newAsyncRESTTemplate()
。我在CompletableFuture
中读到了*Async
方法,但是我应该为它们使用什么Executor
呢?spring是否为theseme提供了一个,或者我应该用线程池创建一个新bean,自动连接它并从中使用池?是的,我认为您必须使用一个spring管理的方法,因为另一个构造函数需要Spr正在初始化接口。例如,新的AsyncRestTemplate(新的ThreadPoolTaskExecutor());-它创建了一个非大小的线程池。有一个ThreadPoolExecutoryFactoryBean,可以用来以某种方式配置JDK ExecutorServices。@Cherry-在这种情况下,在CompletableFuture中不需要*Async方法。提交给a任务执行器比在同一线程上执行慢约10倍(对于标识函数应用程序)。因为您没有使用NIO,所以可以从异步Rest调用恢复线程。