您好,登錄后才能下訂單哦!
這篇文章主要介紹了Spring中@Scheduled限制的問題有哪些,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
@Scheduled具有一定的限制性,它畢竟不是quartz,只是簡單的定時,比jdk Timer就加入了線程池而以
@Scheduled
不支持年份定時
@Scheduled
不支持W L這些字母
沒辦法 如果非要使用那就只能放棄注解使用XML方式了
最近項目中發現一個問題,計劃每日凌晨4:40執行一個定時任務,使用注解方式: @Scheduled(cron = “0 40 4 * * ?”),cron表達式明顯沒有問題,但是這個定時任務總是不按時執行,有時候得等到8點多,有時候9點多才執行。后來查了下,原來這種定時方式默認是單線程執行的,恰好我這里有多個定時任務,并且其中有個在4:40之前的定時任務比較耗時,導致4:40的任務只能等待之前的任務執行完成才能夠觸發,所以要自己手動把定時任務設置成多線程的方式才行。
項目描述:使用Springboot進行開發
設置兩個定時任務,每5s執行一次,并打印出其執行情況
代碼如下:
@Component @Log4j2 public class ScheduledTask { @Scheduled(cron = "0/5 * * * * ?") public void task1() throws InterruptedException { log.info("I am task11111111, current thread: {}", Thread.currentThread()); while (true) { //模擬耗時任務,阻塞10s Thread.sleep(10000); break; } } @Scheduled(cron = "0/5 * * * * ?") public void task2() { log.info("I am task22222222, current thread: {}", Thread.currentThread()); } }
執行結果如下:
2019-04-24 17:11:15.008 INFO 16868 --- [ scheduling-1] com.example.demo.task.ScheduledTask : I am task22222222, current thread: Thread[scheduling-1,5,main]
2019-04-24 17:11:15.009 INFO 16868 --- [ scheduling-1] com.example.demo.task.ScheduledTask : I am task11111111, current thread: Thread[scheduling-1,5,main]
2019-04-24 17:11:25.009 INFO 16868 --- [ scheduling-1] com.example.demo.task.ScheduledTask : I am task22222222, current thread: Thread[scheduling-1,5,main]
2019-04-24 17:11:30.002 INFO 16868 --- [ scheduling-1] com.example.demo.task.ScheduledTask : I am task22222222, current thread: Thread[scheduling-1,5,main]
2019-04-24 17:11:30.003 INFO 16868 --- [ scheduling-1] com.example.demo.task.ScheduledTask : I am task11111111, current thread: Thread[scheduling-1,5,main]
2019-04-24 17:11:40.004 INFO 16868 --- [ scheduling-1] com.example.demo.task.ScheduledTask : I am task22222222, current thread: Thread[scheduling-1,5,main]
由結果可見,task1與task2由同一個線程Thread[scheduling-1,5,main]執行,也即該定時任務默認使用單線程,并且由于task1阻塞了10s,導致本應5s執行一次的定時任務10s才執行一次。
網上有多種解決方案,以下列舉兩種
方案一:使用@Async注解實現異步任務
這種方式比較簡單,在定時任務上加上@Async注解,注意:需啟動類配合加上 @EnableAsync才會生效
代碼如下:
@Component @Log4j2 public class ScheduledTask { @Async @Scheduled(cron = "0/5 * * * * ?") public void task1() throws InterruptedException { log.info("I am task11111111, current thread: {}", Thread.currentThread()); while (true) { //模擬耗時任務,阻塞10s Thread.sleep(10000); break; } } @Async @Scheduled(cron = "0/5 * * * * ?") public void task2() { log.info("I am task22222222, current thread: {}", Thread.currentThread()); } }
運行結果:
2019-04-24 17:03:00.024 INFO 2152 --- [ task-1] com.example.demo.task.ScheduledTask : I am task22222222, current thread: Thread[task-1,5,main]
2019-04-24 17:03:00.024 INFO 2152 --- [ task-2] com.example.demo.task.ScheduledTask : I am task11111111, current thread: Thread[task-2,5,main]
2019-04-24 17:03:05.001 INFO 2152 --- [ task-3] com.example.demo.task.ScheduledTask : I am task11111111, current thread: Thread[task-3,5,main]
2019-04-24 17:03:05.001 INFO 2152 --- [ task-4] com.example.demo.task.ScheduledTask : I am task22222222, current thread: Thread[task-4,5,main]
2019-04-24 17:03:10.002 INFO 2152 --- [ task-5] com.example.demo.task.ScheduledTask : I am task22222222, current thread: Thread[task-5,5,main]
2019-04-24 17:03:10.003 INFO 2152 --- [ task-6] com.example.demo.task.ScheduledTask : I am task11111111, current thread: Thread[task-6,5,main]
由運行日志可見,定時每5s執行一次已生效,且每次任務使用的線程不一樣,也即實現了多線程執行定時任務,不會出現任務等待現象。此方式據說默認線程池大小為100,要是任務不多的話有點大材小用了,所以我覺得第二種方式比較好。
方案二:手動設置定時任務的線程池大小
定時任務代碼部分還原,不使用@Async注解,新增啟動代碼配置:
@Configuration public class AppConfig implements SchedulingConfigurer { @Bean public Executor taskExecutor() { //指定定時任務線程數量,可根據需求自行調節 return Executors.newScheduledThreadPool(3); } @Override public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) { scheduledTaskRegistrar.setScheduler(taskExecutor()); } }
運行結果如下:
2019-04-24 17:26:15.008 INFO 2164 --- [pool-1-thread-2] com.example.demo.task.ScheduledTask : I am task22222222, current thread: Thread[pool-1-thread-2,5,main]
2019-04-24 17:26:15.008 INFO 2164 --- [pool-1-thread-1] com.example.demo.task.ScheduledTask : I am task11111111, current thread: Thread[pool-1-thread-1,5,main]
2019-04-24 17:26:20.002 INFO 2164 --- [pool-1-thread-2] com.example.demo.task.ScheduledTask : I am task22222222, current thread: Thread[pool-1-thread-2,5,main]
2019-04-24 17:26:25.001 INFO 2164 --- [pool-1-thread-2] com.example.demo.task.ScheduledTask : I am task22222222, current thread: Thread[pool-1-thread-2,5,main]
2019-04-24 17:26:30.001 INFO 2164 --- [pool-1-thread-1] com.example.demo.task.ScheduledTask : I am task11111111, current thread: Thread[pool-1-thread-1,5,main]
2019-04-24 17:26:30.001 INFO 2164 --- [pool-1-thread-3] com.example.demo.task.ScheduledTask : I am task22222222, current thread: Thread[pool-1-thread-3,5,main]
2019-04-24 17:26:35.001 INFO 2164 --- [pool-1-thread-3] com.example.demo.task.ScheduledTask : I am task22222222, current thread: Thread[pool-1-thread-3,5,main]
由結果可見,第二種方式也實現了多線程任務調度。
感謝你能夠認真閱讀完這篇文章,希望小編分享的“Spring中@Scheduled限制的問題有哪些”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。