java - Spring boot Async + 多线程在未完成所有任务的情况下关闭
问题描述
Spring boot 在未完成所有任务的情况下关闭。
我想从 MYSQL 数据库中收集数据,然后将这些数据导出为 csv 文件。但是 Spring boot 会在一段时间后关闭。
CompletableFuture.allOf(tasks.toArray(new CompletableFuture[tasks.size()])).join();
不等到所有任务完成。
注意:我有超过 150 个任务需要将数据导出到 CSV 文件。
代码:
MainApplication.java
@SpringBootApplication
@EnableAsync
public class MainApplication implements CommandLineRunner {
@Autowired
private TaskRunner taskrunner;
public static void main(String[] args) throws Exception{
SpringApplication application = new SpringApplication(MainApplication.class);
application.setBannerMode(Banner.Mode.OFF);
application.run(args);
}
public void run(String... args) throws Exception {
taskrunner.executeTasks();
exit(0);
}
}
TaskRunner.java
@Service
public class TaskRunner {
@Autowired
public DataCollector dataCollector;
public void executeTask() throws Exception {
final List<String> parameters = dataCollector.getParameters();
List<CompletableFuture> tasks = new ArrayList<CompletableFuture>();
for (String name : parameters) {
try{
tasks.add(CompletableFuture.runAsync(() -> dataCollector.ExportDataToCsv(name)));
}catch(){
ex.printStackTrace();
System.out.println("Export failed for Param: "+name);
}
}
CompletableFuture.allOf(tasks.toArray(new CompletableFuture[tasks.size()])).join();
System.out.println("All Task Finished");
}
}
数据收集器.java
public class DataCollector{
@Autowired
public DataRepository dataRepository;
@Async("ThreadPoolTaskExecutor")
public CompletableFuture<String> ExportDataToCsv(String tableName){
// Code To export data to csv
}
}
数据存储库.java
@Repository
public class DataRepository {
@Qualifier("jdbcExportService")
@Autowired
public JdbcTemplate jdbcTemplate;
public SqlRowSet getParamData(String param){
String Statement = "select * FROM " + param;
return jdbcTemplate.queryForRowSet(Statement);
}
}
数据库配置.java
@Configuration
public class DatabaseConfiguration {
@Bean(name="db")
@ConfigurationProperties(prefix = "spring.db")
public DataSource createExportDataSource(){
return DataSourceBuilder.create().build();
}
@Bean(name = "jdbcExportService")
@Autowired
public JdbcTemplate createJdbcTemplateExportService(@Qualifier("db") DataSource exportServiceDS){
return new JdbcTemplate(exportServiceDS);
}
}
输出:
2019-06-25 14:39:56.868 INFO 13163 --- [ Thread-2] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'ThreadPoolTaskExecutor'
2019-06-25 14:39:56.868 INFO 13163 --- [ Thread-2] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2019-06-25 14:39:56.997 INFO 13163 --- [ Thread-2] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
2019-06-25 14:39:57.011 DEBUG 13163 --- [ Thread-2] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Before shutdown stats (total=10, active=5, idle=5, waiting=0)
2019-06-25 14:39:57.371 DEBUG 13163 --- [nnection closer] com.zaxxer.hikari.pool.PoolBase : HikariPool-1 - Closing connection com.mysql.cj.jdbc.ConnectionImpl@2c373ded: (connection evicted)
2019-06-25 14:39:57.991 DEBUG 13163 --- [nnection closer] com.zaxxer.hikari.pool.PoolBase : HikariPool-1 - Closing connection com.mysql.cj.jdbc.ConnectionImpl@4856fa0b: (connection evicted)
2019-06-25 14:39:57.994 DEBUG 13163 --- [nnection closer] com.zaxxer.hikari.pool.PoolBase : HikariPool-1 - Closing connection com.mysql.cj.jdbc.ConnectionImpl@375c83e: (connection evicted)
2019-06-25 14:39:57.995 DEBUG 13163 --- [nnection closer] com.zaxxer.hikari.pool.PoolBase : HikariPool-1 - Closing connection com.mysql.cj.jdbc.ConnectionImpl@417d7b5b: (connection evicted)
2019-06-25 14:39:57.996 DEBUG 13163 --- [nnection closer] com.zaxxer.hikari.pool.PoolBase : HikariPool-1 - Closing connection com.mysql.cj.jdbc.ConnectionImpl@77ebb3e9: (connection evicted)
2019-06-25 14:39:58.094 DEBUG 13163 --- [ Thread-2] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - After shutdown stats (total=0, active=0, idle=0, waiting=0)
2019-06-25 14:39:58.095 INFO 13163 --- [ Thread-2] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
2019-06-25 14:39:58.651 WARN 13163 --- [ export-thread1] com.zaxxer.hikari.pool.ProxyConnection : HikariPool-1 - Connection com.mysql.cj.jdbc.ConnectionImpl@4c18c2a2 marked as broken because of SQLSTATE(08003), ErrorCode(0)
解决方案
我读了一点后的猜测,我绝不是这方面的专家。所以这很可能是错误的。
CompletableFuture#join
等到您可以从该 CompletableFuture 中提取结果值。CompletableFuture#get
抛出检查异常并且CompletableFuture#join
是不可中断的。但是两者都做同样的事情,从可完成的未来中提取价值,并在需要时阻止,直到他们这样做。
我认为您正在寻找什么,因为您想在完成后打印某些内容是使用CompletableFuture#thenAccept
将在所有内容完成后执行“某事”的东西。
CompletableFuture<Void> allFutures = CompletableFuture.allOf(tasks.toArray(new CompletableFuture[tasks.size()]));
allFutures.thenAccept(Void -> System.out.println("All Task Finished"));
我的猜测是它设置了所有异步任务,然后将其全部传递,然后退出应用程序。
参考:
推荐阅读
- javascript - React getDerivedStateFromProps 无法访问此
- java - 如何让信任锚在 Android API 级别 16-19 上正常工作
- php - “字段列表”mySQL Wordpress php中的未知列“数量”
- android - 无法创建新会话,因为未找到需要 HttpClient、InputStream 和 long 的“createSession”或无法访问
- php - PHP中的随机关联数组值
- html - 如果元素具有具有相对位置的子项,则滚动条在溢出隐藏下显示(Google Chrome - Mac OS)
- java - 如何使用 IAIK JCE 在 Java 中使用 PKCS#5 格式的 PBE 加密 RSA 私钥?
- java - 何时使用 @NotNull 和 @Nullable IntelliJ 注释?
- c# - 双重转义和 + 符号
- java - 从我的应用程序向拨号器发送号码