Spring 启动异步任务卡在关机状态

Spring Boot async task stuck on shutdown

根据 spring setWaitForTasksToCompleteOnShutdown

的文档

Set whether to wait for scheduled tasks to complete on shutdown

这是否意味着如果任何任务卡在某个较长的 运行 进程中并且我们明确尝试停止容器,则在该任务完成之前它不会终止?

  @Bean
  public TaskExecutor myAsyncTaskExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(20);
    executor.setMaxPoolSize(30);
    executor.setQueueCapacity(50);
    executor.setWaitForTasksToCompleteOnShutdown(true); // How it behaves?
    //executor.afterPropertiesSet();
    executor.setThreadNamePrefix("MY-ASYNC-TASK");
    executor.initialize();
    return executor;
  }

感谢您的回答。

简答?是

默认情况下,关闭时(通过请求关闭端点或调用 applicationcontext.close),Spring 的 TaskExecutor 会简单地中断所有 运行 任务。

请注意,您的线程必须处于可中断状态(例如睡眠)才能真正被中断。

在某些情况下,您可能希望等待所有 运行 任务完成。

调用 setWaitForTasksToCompleteOnShutdown(true) 只是防止在关机时中断 运行 任务,并确保当前正在执行的任务和排队的任务都已完成。

(我认为这是因为它们是阻止应用程序退出的非守护线程。)

总之,你的问题的答案是肯定的。

你可以玩下面的代码。当您将 setWait 从 false 更改为 true 时,您会看到在睡眠结束之前应用程序不会退出。当您将其设置为 false 时,应用程序将立即终止。

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;


@SpringBootApplication
public class Application {
    @Autowired
    private TaskExecutor taskExecutor;
    
    @Bean
    public TaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(2);
        taskExecutor.setMaxPoolSize(2);
        taskExecutor.setWaitForTasksToCompleteOnShutdown(false);
        taskExecutor.initialize();
        return taskExecutor;
    }
    
    @PostConstruct
    public void runTaskOnStartup() {
        for (int i = 0; i < 1; i++) {
            taskExecutor.execute(() -> {
                try {
                    Thread.sleep(10_000);
                } catch (InterruptedException e) {
                    System.out.println("Sleep Interrupted!");
                    e.printStackTrace();
                }
            });
        }
    }
    
    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(Application.class, args);
        run.close();
    }
}