![](/img/trans.png)
[英]Async call of a FeignClient Springboot with CompletableFuture
[英]SpringBoot-2.1.3: Parallel Methods Invocation with @Async with CompletableFuture
下面是我的代码,我在其中尝试并行化 4 个方法调用,因为每个方法彼此独立并执行一些内存密集型统计操作。
@EnableAsync
@Configuration
public class Config {
@Bean(name = "threadPoolTaskExecutor")
public Executor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.initialize();
return executor;
}
}
class OrderStatsService{
public CumulativeStats compute() {
log.info("CumulativeResult compute started at " + System.currentTimeMillis() + ", Current Thread Name: " + Thread.currentThread().getName() + ", Current Thread ID: " + Thread.currentThread().getId());
List<Order> orders = getOrders();// API Call to fetch large set of orders size could be around 100k
CumulativeResult cumulativeResult = new CumulativeResult();
CompletableFuture<Long> stats1 = getStats1(orders);
CompletableFuture<List<String>> result2 = getStats2(orders);
CompletableFuture<Double> result3 = getStats3(orders);
CompletableFuture<Map<String,String>> result4 = getStats4(orders);
cumulativeResult.setStats1(stats1);
cumulativeResult.setStats2(stats2);
cumulativeResult.setStats3(stats3);
cumulativeResult.setStats4(stats4);
return cumulativeResult;
}
@Async("threadPoolTaskExecutor")
public CompletableFuture<Long> getStats1(var orders) {
log.info("getStats1 started at " + System.currentTimeMillis() + ", Current Thread Name: " + Thread.currentThread().getName() + ", Current Thread ID: " + Thread.currentThread().getId());
//computes some stats
}
@Async("threadPoolTaskExecutor")
public CompletableFuture<List<String>> getStats2(var orders) {
log.info("getStats2 started at " + System.currentTimeMillis() + ", Current Thread Name: " + Thread.currentThread().getName() + ", Current Thread ID: " + Thread.currentThread().getId());
//computes some stats
}
@Async("threadPoolTaskExecutor")
public CompletableFuture<Double> getStats3(var> orders) {
log.info("getStats3 started at " + System.currentTimeMillis() + ", Current Thread Name: " + Thread.currentThread().getName() + ", Current Thread ID: " + Thread.currentThread().getId());
//computes some stats
}
@Async("threadPoolTaskExecutor")
public CompletableFuture<Map<String,String>> getStats4(var orders) {
log.info("getStats4 started at " + System.currentTimeMillis() + ", Current Thread Name: " + Thread.currentThread().getName() + ", Current Thread ID: " + Thread.currentThread().getId());
//computes some stats
}
}
我得到了预期的结果,但注意到调用compute()
的主线程也在执行其他 4 个方法getStats1
、 getStats2
、 getStats3
、 getStats4
方法。
CumulativeResult compute started at 1655783237437, Current Thread Name: http-nio-8080-exec-1, Current Thread ID: 28
getStats1 started at 1655783238022, Current Thread Name: http-nio-8080-exec-1, Current Thread ID: 28
getStats2 started at 1655783238024, Current Thread Name: http-nio-8080-exec-1, Current Thread ID: 28
getStats3 started at 1655783463062, Current Thread Name: http-nio-8080-exec-1, Current Thread ID: 28
getStats4 started at 1655783238085, Current Thread Name: http-nio-8080-exec-1, Current Thread ID: 28
我想当我们将CompletableFuture
用于带有@EnableAsync
配置的@Async
方法时,这些方法将被分配一个新线程来执行它们,有人可以解释一下这是并行方法调用的预期行为吗? 我的配置有什么问题吗? 或者,如果这是我们在同一线程中执行caller
方法和async
时如何实现并行性的预期行为?
可以在代码中进行所需的更改。
第 1 步:执行多线程的第一步是正确设置线程池配置。
这是一个如何设置线程大小的示例
@Configuration
@EnableAsync
public class ThreadPoolConfiguration {
@Bean(name = "taskExecutor")
public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.setThreadNamePrefix("thread-");
threadPoolTaskExecutor.setCorePoolSize(100);
threadPoolTaskExecutor.setMaxPoolSize(120);
threadPoolTaskExecutor.setQueueCapacity(100000);
threadPoolTaskExecutor.initialize();
return threadPoolTaskExecutor;
}
第二步:使用@Async注解
首先,让我们回顾一下规则。
有关@Async 的更多信息,您可以通过
解决方案:
@Async("taskExecutor")
之类的 Bean 名称标记您的注释任何一种方式都适合你。
您应该设置线程池大小以控制线程数:
final ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(2);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("CarThread-");
我建议检查一些事实:
OrderStatsService
类是static
的吗?它是由 Spring 管理的Bean
吗?Bean
的@Async
方法必须直接从它的调用者调用。 您在OrderStatsService
( Bean
-如果您已经这样做了)中拥有的是调用non-@Async
@Async 方法,然后调用@Async
方法。 以我的经验,这不会给你预期的行为。如果我是一个愚蠢的笨蛋,请随时纠正我。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.