问题:
使用了springboot定时任务对多个表数据进行操作,当容器销毁时,导致定时任务执行过程中突然终止,数据操作未全部完成,最后造成数据没有闭环。
解决方案一:
指定springBoot定时任务使用的线程池配置
@Configuration
public class ThreadPoolTaskSchedulerConfig {
/**
* taskScheduler.
*
* @return ThreadPoolTaskScheduler to replace spring boot schedule thread pool.
*/
@Bean
public ThreadPoolTaskScheduler taskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
// 线程池大小设置为10
scheduler.setPoolSize(10);
// 确保在关闭时等待任务完成
scheduler.setWaitForTasksToCompleteOnShutdown(true);
// 设置最大等待时长,以确保应用最后能够被关闭,而不是阻塞住
scheduler.setAwaitTerminationSeconds(60);
return scheduler;
}
}
解决方案二:
增加钩子函数,监听到容器销毁事件时,使用shoutdown关闭定时任务,然后设置最大等待时间
shutdown
拒绝新任务提交
待执行的任务不会取消
正在执行的任务也不会取消,将继续执行
shutdownNow
拒绝新任务提交
取消待执行的任务
尝试取消执行中的任务(仅仅是做尝试,成功与否取决于是否响应InterruptedException,以及对其做出的反应)
@Component
public class SchedulerDestroyer {
@Autowired
private ThreadPoolTaskScheduler taskScheduler;
@PreDestroy
public void preDestroy() {
taskScheduler.shutdown();
taskScheduler.setAwaitTerminationSeconds(60);
}
}
测试用例
@Component
public class SchedulerTest {
private static boolean tasksCompleted = false;
@Scheduled(fixedDelay = 1000)
public void longRunningTask() {
setTasksCompleted(false);
System.out.println("定时任务开始执行");
int a = 0;
// 模拟长时间运行的任务
for (int i = 0; i < 1000 ; i++) {
int s = 0;
for (int j = 0; j < 10000; j++) {
s += j;
System.out.println(s);
}
a += i;
}
System.out.println("定时任务执行完成" + a);
setTasksCompleted(true);
}
public void setTasksCompleted(boolean tasksCompleted) {
SchedulerTest.tasksCompleted = tasksCompleted;
}
}