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();
}
}
根据 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();
}
}