springboot定時任務優雅退出方案

枫树湾河桥發表於2024-08-21

問題:
使用了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;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
解決方案二:
增加鉤子函式,監聽到容器銷燬事件時,使用shoutdown關閉定時任務,然後設定最大等待時間
shutdown
拒絕新任務提交
待執行的任務不會取消
正在執行的任務也不會取消,將繼續執行
shutdownNow
拒絕新任務提交
取消待執行的任務
嘗試取消執行中的任務(僅僅是做嘗試,成功與否取決於是否響應InterruptedException,以及對其做出的反應)

@Component
public class SchedulerDestroyer {

@Autowired
private ThreadPoolTaskScheduler taskScheduler;

@PreDestroy
public void preDestroy() {
taskScheduler.shutdown();
taskScheduler.setAwaitTerminationSeconds(60);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
測試用例
@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;
}
}
————————————————

版權宣告:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處連結和本宣告。

原文連結:https://blog.csdn.net/qq_44913073/article/details/139216828

相關文章