当前位置: 首页 > 知识库问答 >
问题:

Spring boot Async+多线程在未完成所有任务的情况下关闭

凌俊名
2023-03-14

Spring引导在没有完成所有任务的情况下关闭。

 CompletableFuture.allOf(tasks.toArray(new CompletableFuture[tasks.size()])).join();

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);
   }
}

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");
  }
}

datacollector.java

public class DataCollector{

@Autowired
public DataRepository dataRepository;

 @Async("ThreadPoolTaskExecutor")
 public CompletableFuture<String> ExportDataToCsv(String tableName){
   // Code To export data to csv
 }
}
@Repository
public class DataRepository {

   @Qualifier("jdbcExportService")
   @Autowired
   public JdbcTemplate jdbcTemplate;

   public SqlRowSet getParamData(String param){
    String Statement = "select * FROM " + param;
    return jdbcTemplate.queryForRowSet(Statement);
  }
}
 @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)

共有1个答案

黎苑博
2023-03-14

我的猜测后读了一点,我在这方面绝不是专业的。所以这很可能是错误的。

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"));

Java-8-CompletableFuture-In-Action

CompletableFuture-join-vs-get

 类似资料:
  • 问题内容: 我不能使用,因为有可能在等待时将新任务添加到ThreadPoolExecutor中。 因此,我正在寻找一种方法,等待ThreadPoolExecutor清空队列并完成所有任务,而又不阻止在此之前添加新任务。 如果有什么不同,这适用于Android。 谢谢 更新 :几周后,我再次进行了修改,发现在这种情况下,修改后的CountDownLatch对我而言效果更好。我会保留答案,因为它更适用

  • 问题内容: 我是python和线程的新手。我已经编写了充当网络爬虫的python代码,并在网站中搜索特定的关键字。我的问题是,如何使用线程同时运行类的三个不同实例。当实例之一找到关键字时,所有三个实例都必须关闭并停止爬网。这是一些代码。 如何使用线程让Crawler同时执行三个不同的爬网? 问题答案: 似乎没有一种(简单的)方法可以终止Python中的线程。 这是一个并行运行多个HTTP请求的简单

  • 我的遗嘱执行人服务是这样的: 实现了runnable,它的run方法具有巨大的功能,需要调用其他几个API。现在,当我在调试模式下运行代码时,任务就完成了。当我正常运行时,任务是不完整的,线程被终止。线程不是要等到所有任务都完成了吗?为什么他们没有完成任务就被解雇了?

  • 这可能是在类似的背景下问的,但我在搜索了大约20分钟后找不到答案,所以我会问。 我已经编写了一个Python脚本(比如说:scriptA.py)和一个脚本(比如说scriptB.py) 在scriptB中,我想用不同的参数多次调用scriptA,每次运行大约需要一个小时,(这是一个巨大的脚本,做了很多事情……不用担心),我希望能够同时使用所有不同的参数运行scriptA,但我需要等到所有参数都完成

  • 我正在使用Spring 4.3.8。发布Java7。我想创建一个线程工厂来帮助管理应用程序中的某些工作人员。我像这样声明我的线程工厂 但是,我在线程上“加入”有困难。也就是说,我想在继续某个任务之前等待所有工作完成,所以我有 我的线程池是这样执行的 然而打印出来的是 所以很明显我没有等待。等待我的线程完成工作的正确方法是什么?

  • 问题内容: 该代码选择同一文件夹中的所有xml文件,作为被调用的可执行文件,并以异步方式将处​​理应用于回调方法中的每个结果(在下面的示例中,仅打印文件名)。 如何避免使用sleep方法阻止main方法退出?我在解决问题时遇到了麻烦(我想这就是同步结果所必需的),因此,我们将不胜感激! 问题答案: 您可以使用sync.WaitGroup。引用链接的示例: