后端系統(tǒng)經(jīng)常會遇到定時執(zhí)行某個任務(wù)的需求,如果這個任務(wù)只是后端的一個方法,沒有太過復(fù)雜的關(guān)聯(lián)邏輯,那么我們只需要配合Spring框架提的供定時任務(wù)注解@Scheduled再加上一個Cron表達式便可輕輕松松滿足需求,沒錯,實現(xiàn)就是這么簡單。
但是功能到生產(chǎn)環(huán)境以后發(fā)現(xiàn)一個問題,定時任務(wù)并沒有按照我們預(yù)定的執(zhí)行計劃執(zhí)行,經(jīng)常會漏執(zhí)行,很奇怪,這是為神馬?
給所有定時任務(wù)加日志,發(fā)現(xiàn)一個規(guī)律,如果程序里面有多個定時任務(wù),則每一個定時任務(wù)的日志是串行打印的,并沒有想象中的并行打印,也就是這些定時任務(wù)同時只有一個線程在執(zhí)行。google一下資料,果然,Spring默認(rèn)給所有定時任務(wù)只分配了一個線程,這樣的話如果我們有很多定時任務(wù)或者一個定時任務(wù)執(zhí)行很久,就會造成其他定時任務(wù)阻塞中,無法按照cron執(zhí)行的情況。
解決辦法就是程序里面用了多少定時任務(wù)注解@Scheduled,就初始化多少線程,這樣各個定時任務(wù)就不會互相影響了。
代碼如下:
@Configuration
//定時任務(wù)調(diào)用一個線程池中的線程。
public class ScheduleConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
//參數(shù)傳入一個size為10的線程池
scheduledTaskRegistrar.setScheduler(Executors.newScheduledThreadPool(10));
}
}
另外還需要注意一個問題,就是單個定時任務(wù)最好保證在指定的執(zhí)行計劃內(nèi)執(zhí)行完畢,否則依然會出現(xiàn)該定時任務(wù)跳過當(dāng)次執(zhí)行的問題。