我加入了公司的一个新团队,我看到他们广泛使用“threadpooltaskexecutor”。它基本上是一个前端的后端rest应用程序,它调用其他soap API并将结果返回给客户机—只是一个传递。99%的情况下,每个rest端点只调用一个soap api,并将json格式的响应返回给客户端。不过,尽管这只是一个soap调用,但它们使用“threadpooltaskexecutor”并调用.get()阻塞方法。
@configuration class上的threadpooltaskexecutor@bean:
@Bean(name=“soapAsyncExecutor")
@Qualifier("soapAsyncExecutor")
public ThreadPoolTaskExecutor getSoapAsyncExecutor() {
final ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
final ThreadFactory customThreadfactory = new ThreadFactoryBuilder()
.setNameFormat(“SoapExecutor-%d")
.setUncaughtExceptionHandler(uncaughtExceptionHandler())
.setDaemon(true)
.build();
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setCorePoolSize(80);
executor.setMaxPoolSize(200);
executor.setQueueCapacity(80);
executor.setKeepAliveSeconds(60);
executor.setAllowCoreThreadTimeOut(true);
executor.setThreadFactory(customThreadfactory);
executor.afterPropertiesSet();
return executor;
}
@service上的代码:
@Async("soapAsyncExecutor")
@Override
public Future<OrderInfo> getOrderInfoAsync(final String orderId) {
return new AsyncResult<OrderInfo>(this.getOrderInfo(orderId);
}
private OrderInfo getOrderInfo(final String orderId) {
// return result from SOAP call which typically take 1 second
}
然后从上面的@restcontroller异步方法调用如下:
@GetMapping(value = "/order/{orderId}")
public OrderInfo getOrderInfo(@PathVariable("orderId") final String orderId) {
OrderInfo orderInfo = orderService.getOrderInfoAsync(orderId).get();
return orderInfo;
}
据我所知,spring中对rest端点的每个请求都会产生一个新线程(因为我没有更好的词,所以我们称之为主线程)。在那里调用“.get()”方法会阻塞主线程。我的问题是,在这个封锁期,
官方的主线是什么状态——“封锁”还是“等待”?如果被阻塞了,那么对单个作业使用这样的“threadpooltaskexecutor”是否有一点好处,因为它会阻塞主线程?
是否可以通过任何方式调整此代码以带来好处,或者在restcontroller端点中对这样的单个作业使用异步编程是没有意义的?
1条答案
按热度按时间vwkv1x7d1#
官方的主线是什么状态——“封锁”还是“等待”?
此 路 不通。
如果被阻塞了,那么对单个作业使用这样的“threadpooltaskexecutor”是否有一点好处,因为它会阻塞主线程?
不。没有。事实上,我打赌将任务分派到线程池会带来额外的开销。不过,如果端点要等待多个任务完成,这是有意义的。
是否可以通过任何方式调整此代码以带来好处,或者在restcontroller端点中对这样的单个作业使用异步编程是没有意义的?
当然。下面是一个例子。这是另一个。基本上,在您的场景中,只要返回
CompletableFuture
而不是打电话.get()
.