@Schedule 如何解決定時任務推遲執行
前言
SpringBoot 實現定時任務很簡單,隻需要使用**@Scheduled**註解即可,但是該註解是實現的定時任務默認是單線程的,也就意味著多個定時任務執行時就可能導致線程堵塞,延緩定時任務的執行。
下面就一步一步來解決這個問題。
一、@Scheduled
1、代碼
// 啟用定時任務 @EnableScheduling @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
@Component public class Task { Logger logger = LoggerFactory.getLogger(Task.class); // 每五秒執行一次 @Scheduled(cron = "0/5 * * * * ?") public void taskTestA() throws InterruptedException { logger.info("A:"); TimeUnit.SECONDS.sleep(20); } // 每十秒執行一次 @Scheduled(cron = "0/10 * * * * ?") public void taskTestB() { logger.info("B:"); } }
2、結果
由圖可知,首先這兩個定時任務都是單線程的,但是當定時A執行瞭一次後,由於定時A中有個休眠20秒,然後執行定時任務B,所以線程A第二次執行在25秒後才執行,這就是由於@Scheduled定時任務是單線程,造成的線程堵塞,導致定時任務推遲執行。
二、@Scheduled + 配置線程池
1、代碼
和前面@Scheduled 相比,僅僅增加瞭配置線程池
// 若不設置默認為單線程,這裡設置使用線程池,大小為4 spring: task: scheduling: pool: size: 4
2、結果
由圖可知,增加瞭線程池,這樣使得定時任務A和B在不同的線程進行執行,但是定時任務A的第二次執行,依舊是在25秒後執行,由此可知這種方式其實解決的是不同定時任務之間的進程堵塞。
三、@Scheduled + @Async
1、代碼
和前面相比,僅僅增加瞭配置
// 啟用異步,動態創建線程 @EnableAsync @EnableScheduling @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
@Component public class Task { Logger logger = LoggerFactory.getLogger(Task.class); // 異步,動態創建線程 @Async @Scheduled(cron = "0/5 * * * * ?") public void taskTestA() throws InterruptedException { logger.info("A:"); TimeUnit.SECONDS.sleep(20); } // 異步,動態創建線程 @Async @Scheduled(cron = "0/10 * * * * ?") public void taskTestB() { logger.info("B:"); } }
2、結果
由圖可知,啟用瞭異步,使用瞭spring 默認的線程池,動態創建線程,這樣使得定時任務A和B在不同的線程進行執行,同時任務A的多次運行也是異步執行,這樣就能確保所有定時任務不會延遲執行!
以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。
推薦閱讀:
- Java spring定時任務詳解
- SpringBoot定時任務多線程實現示例
- Spring Task 動態修改任務執行計劃cron方式
- Spring Schedule Task動態改寫Cron配置方式
- springboot定時任務@Scheduled執行多次的問題