定時任務注解@Scheduled不生效問題及解決
定時任務注解@Scheduled不生效
問題描述
在用@Scheduled做定時任務的注解時,發(fā)現(xiàn)@Scheduled注解不生效。
原因分析
用能要交給spring容器的注解
比如@Component注解。
使用@EnableScheduling
啟動類里面/使用定時任務所在的類中使用@EnableScheduling 注解開啟功能,自動掃描
cron表達式寫法不對
正常寫法:@Scheduled(cron="*/10 * * * * ?")
代表10s執(zhí)行一次,每個對應的是秒 分 時 天
如果是想每天0:30執(zhí)行一次,那就是:
正常寫法:@Scheduled(cron=“0 30 0 * * ?”)
使用apollo添加配置后,apollo修改配置后不生效
在使用@Scheduled時,項目啟動時已將時間注入Spring容器中。
相當于就算是apollo改了內容有熱加載機制,值也不會生效。
如果想生效,需要重啟服務。
@Scheduled實現(xiàn)定時任務(實現(xiàn)多個定時任務并發(fā)執(zhí)行)
@Scheduled實現(xiàn)定時任務
使用@Scheduled注解需要springboot啟動類上添加注解@EnableScheduling
@SpringBootApplication @MapperScan(basePackages = {"com.xxx.*.mapper"}) @EnableScheduling public class PictureProcessingAdminApplication{ public static void main(String[] args) { SpringApplication.run(PictureProcessingAdminApplication.class, args); } }
同個任務的同步執(zhí)行
同步執(zhí)行:等待上一次定時任務結束后才開始cron表達式時間匹配
注意:同步任務所在類必須被spring掃描所管理才行,所以需要添加@Component注解。
很多人明明在方法在添加了@Scheduled注解,但是不生效都是這個原因,定時任務所在類沒有被spring管理。
@Component public class taskTest { @Scheduled(cron = "0 */1 * * * ?") public void task1(){ try { System.out.println("任務1執(zhí)行:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(System.currentTimeMillis()))); Thread.sleep(65000); System.out.println("任務1結束:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(System.currentTimeMillis()))); } catch (InterruptedException e) { e.printStackTrace(); } } }
同個任務的并發(fā)執(zhí)行
相對同步執(zhí)行來說,定時任務方法頭部增加@Async即可實現(xiàn)并發(fā)執(zhí)行,也就是嚴格按照cron表達式進行時間匹配執(zhí)行,無需等待上一次任務執(zhí)行結束。
@Component public class taskTest { @Async @Scheduled(cron = "0 */1 * * * ?") public void task1(){ try { System.out.println("任務1執(zhí)行:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(System.currentTimeMillis()))); Thread.sleep(65000); System.out.println("任務1結束:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(System.currentTimeMillis()))); } catch (InterruptedException e) { e.printStackTrace(); } } }
多個任務的同步執(zhí)行
任務使用@Scheduled
然后最重要的是,需要將springboot維護的ThreadPoolTaskScheduler定時任務線程池的長度設置為大于定時任務個數(shù)的值。然后ThreadPoolTaskScheduler默認長度為1。所以默認只有一個定時任務在跑。
源碼如下:
所以,需要將ThreadPoolTaskScheduler的長度修改即可,在項目啟動時,設置長度,替換原本springboot管理的bean即可。
@Component public class TaskSchedulerConfig { @Bean public ThreadPoolTaskScheduler threadPoolTaskScheduler(){ ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler(); threadPoolTaskScheduler.setPoolSize(10); return threadPoolTaskScheduler; } }
總結
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
SpringSecurity HttpSecurity 類處理流程分析
SpringSecurity在SSM項目中使用基于配置文件,通過XML標簽定義認證信息,HttpSecurity在SpringBoot中通過代碼配置實現(xiàn)與XML相同功能,詳細介紹了HttpSecurity的類結構、處理過程及其與SecurityBuilder的關系,感興趣的朋友一起看看吧2024-09-09使用Java進行FreeMarker的web模板開發(fā)的基礎教程
這篇文章主要介紹了使用Java進行FreeMarker模板引擎開發(fā)的基礎教程,文中針對FreeMarker的網頁標簽用法給出了一些例子,需要的朋友可以參考下2016-03-03Java中使用數(shù)組實現(xiàn)棧數(shù)據(jù)結構實例
這篇文章主要介紹了Java中使用數(shù)組實現(xiàn)棧數(shù)據(jù)結構實例,本文先是講解了實現(xiàn)棧至少應該包括以下幾個方法等知識,然后給出代碼實例,需要的朋友可以參考下2015-01-01