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