Spring內(nèi)置定時任務(wù)調(diào)度@Scheduled使用詳解
Spring提供了@Scheduled注解用于定時任務(wù)。
一、@Scheduled的基本使用
啟用調(diào)度支持:@EnableScheduling
可以將@Scheduled注釋與觸發(fā)器元數(shù)據(jù)一起添加到方法中。例如,以下方法每隔5秒調(diào)用一次,并具有固定的延遲,這意味著周期是從前面每次調(diào)用的完成時間開始計算的
@Scheduled(fixedDelay=5000)public void doSomething() {// something that should execute periodically}
如果需要固定速率執(zhí)行,可以更改批注中指定的屬性名。以下方法每5秒調(diào)用一次(在每次調(diào)用的連續(xù)開始時間之間計算)
@Scheduled(fixedRate=5000)public void doSomething() {// something that should execute periodically}
對于固定延遲和固定速率任務(wù),可以通過指示在首次執(zhí)行方法之前要等待的毫秒數(shù)來指定初始延遲
@Scheduled(initialDelay=1000, fixedRate=5000)public void doSomething() {// something that should execute periodically}
如果簡單的周期性調(diào)度不夠表達,可以提供cron表達式。例如,以下命令僅在工作日執(zhí)行:
@Scheduled(cron='*/5 * * * * MON-FRI')public void doSomething() {// something that should execute on weekdays only}
實現(xiàn)SchedulingConfigurer接口,重寫configureTasks方法:
@Schedule注解的一個缺點就是其定時時間不能動態(tài)更改,它適用于具有固定任務(wù)周期的任務(wù),若要修改任務(wù)執(zhí)行周期,只能走“停服務(wù)→修改任務(wù)執(zhí)行周期→重啟服務(wù)”這條路。而基于 SchedulingConfigurer 接口方式可以做到。SchedulingConfigurer 接口可以實現(xiàn)在@Configuration等注解類上。
ScheduledTaskRegistrar類包括以下幾個重要方法:
void addTriggerTask(Runnable task, Trigger trigger) void addTriggerTask(TriggerTask task)void addCronTask(Runnable task, String expression)void addCronTask(CronTask task)void addFixedRateTask(Runnable task, long interval)void addFixedRateTask(IntervalTask task)void addFixedDelayTask(Runnable task, long delay)void addFixedDelayTask(IntervalTask task)
具體實現(xiàn)參考如下:
@Componentpublic class TestTask implements SchedulingConfigurer { @Override public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { taskRegistrar.addTriggerTask(new Runnable() { @Override public void run() {// 定時任務(wù)要執(zhí)行的內(nèi)容System.out.println('【開始執(zhí)行定時任務(wù)。。?!?); } }, new Trigger() { @Override public Date nextExecutionTime(TriggerContext triggerContext) {// 定時任務(wù)觸發(fā),可修改定時任務(wù)的執(zhí)行周期String cron = '0 0/5 * * * ?'; //可以將表達式配置在數(shù)據(jù)庫中CronTrigger trigger = new CronTrigger(cron);Date nextExecDate = trigger.nextExecutionTime(triggerContext);return nextExecDate; } }); }}
提示:如果在數(shù)據(jù)庫修改時格式出現(xiàn)錯誤,則定時任務(wù)會停止,即使重新修改正確;此時只能重新啟動項目才能恢復(fù)。
二、使用@Scheduled注意事項
spring的注解@Scheduled 需要寫在實現(xiàn)方法上; 定時器的任務(wù)方法不能有返回值(如果有返回值,spring初始化的時候會告訴你有個錯誤、需要設(shè)定一個proxytargetclass的某個值為true),不能指向任何的參數(shù); 如果該方法需要與應(yīng)用程序上下文的其他對象進行交互,通常是通過依賴注入來實現(xiàn); 實現(xiàn)類上要有組件的注解@Component。三、使用@Scheduled常見問題
單線程任務(wù)丟失,轉(zhuǎn)為異步線程池
默認(rèn)的 ConcurrentTaskScheduler 計劃執(zhí)行器采用Executors.newSingleThreadScheduledExecutor() 實現(xiàn)單線程的執(zhí)行器。因此,對同一個調(diào)度任務(wù)的執(zhí)行總是同一個線程。如果任務(wù)的執(zhí)行時間超過該任務(wù)的下一次執(zhí)行時間,則會出現(xiàn)任務(wù)丟失,跳過該段時間的任務(wù)。上述問題有以下解決辦法:
采用異步的方式執(zhí)行調(diào)度任務(wù),配置 Spring 的 @EnableAsync,在執(zhí)行定時任務(wù)的方法上標(biāo)注 @Async配置任務(wù)執(zhí)行池,線程池大小 n 的數(shù)量為 單個任務(wù)執(zhí)行所需時間 / 任務(wù)執(zhí)行的間隔時間。如下:
//每30秒執(zhí)行一次@Async('taskExecutor')@Scheduled(fixedRate = 1000 * 3)public void reportCurrentTime(){ System.out.println ('線程' + Thread.currentThread().getName() + '開始執(zhí)行定時任務(wù)===&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&7&&&====》' + new SimpleDateFormat('yyyy-MM-dd HH:mm:ss').format(new Date())); long start = System.currentTimeMillis();}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持好吧啦網(wǎng)。
相關(guān)文章:
