异步方法调用完成后 Spring 命令行应用程序挂起

And*_*ose 8 java spring multithreading asynchronous spring-boot

我有一个 Spring Boot 应用程序,它使用CommandLineRunnerSpring@Async注释来异步运行方法。一切正常,但是当我的所有线程完成时,应用程序只是挂起而不是退出。

这是我的应用程序中的一个最小示例:

应用程序.java

@SpringBootApplication
@EnableAsync
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
Run Code Online (Sandbox Code Playgroud)

应用程序启动.java

@Component
public class ApplicationStartup implements CommandLineRunner {

    private final AsyncService asyncService;

    @Inject
    public ApplicationStartup(final AsyncService asyncService) {
        this.asyncService = asyncService;
    }

    @Override
    public void run(final String... strings) throws Exception {
        //my logic is more complicated than this, but this illustrates my point
        for (int i = 0; i < 1000; i++) {
            asyncService.runAsyncMethod();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

AsyncService.java

@Service
@Transactional
public class AsyncService {

    @Async
    public void runAsyncMethod() {
        //perform call to an API and process results
    }

}
Run Code Online (Sandbox Code Playgroud)

ExecutorConfig.java

@Configuration
public class ExecutorConfig() {
    @Bean
    public ThreadPoolTaskExecutor asyncExecutor() {
        final ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(64);
        executor.setMaxPoolSize(64);
        executor.setQueueCapacity(500);
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.setThreadNamePrefix("Scrub-");
        executor.setKeepAliveSeconds(60);
        executor.initialize();
        return executor;
    }
}
Run Code Online (Sandbox Code Playgroud)

我的所有线程都进行调用runAsyncMethod()并且每个方法调用都成功完成,但随后应用程序只是挂起。

我尝试更改一些执行器设置。我一开始没有keepAliveSeconds,所以我想添加它可以修复它,但在所有线程完成后它仍然挂起。我更改corePoolSize0,这使得应用程序在完成后退出,但它始终只使用 1 个线程。

关于为什么应用程序没有以上述配置退出的任何想法?

xer*_*593 3

您错过了加入异步作业,这就是该run方法在所有线程完成之前(远远)退出的原因 - 并且这种尴尬的行为“更容易理解”。

根据doc,你可以加入:

...
CompletableFuture<Void>[] myJobs = new CompletableFuture<>[N];
...
for (int i = 0; i < N; i++) {
        myJobs[i] = asyncService.runAsyncMethod();
}
...
CompletableFuture.allOf(myJobs).join();
Run Code Online (Sandbox Code Playgroud)

runAsyncMethod()需要返回一个CompletableFuture<Void>. 为此,您只需return CompletableFuture.completedFuture(null);