解決定時(shí)任務(wù)@Scheduled沒(méi)有準(zhǔn)時(shí)執(zhí)行的原因及分析
定時(shí)任務(wù)@Scheduled沒(méi)有準(zhǔn)時(shí)執(zhí)行的原因
項(xiàng)目中用到了定時(shí)任務(wù)往前端推送數(shù)據(jù),間隔2秒 @Scheduled(cron = "0/2 * * * * ? "),測(cè)試發(fā)現(xiàn),每次任務(wù)執(zhí)行并不是2秒,而是1-5秒之間。
執(zhí)行時(shí)間:::::Wed Nov 30 16:20:19 CST 2022
執(zhí)行時(shí)間:::::Wed Nov 30 16:20:20 CST 2022
執(zhí)行時(shí)間:::::Wed Nov 30 16:20:24 CST 2022
執(zhí)行時(shí)間:::::Wed Nov 30 16:20:29 CST 2022
原因
了解發(fā)現(xiàn),如果程序中沒(méi)有指定線程池的配置,也就是Spring的Scheduled的默認(rèn)線程池配置,其線程池的線程數(shù)默認(rèn)為1,也就是說(shuō)默認(rèn)情況下,Spring用來(lái)處理定時(shí)任務(wù)的線程只有一個(gè)。
如果有定時(shí)的處理時(shí)間占用時(shí)間比較長(zhǎng),那么就會(huì)導(dǎo)致下一個(gè)定時(shí)任務(wù),即使到達(dá)了配置的定時(shí)時(shí)間,也不會(huì)立即執(zhí)行,而是等到前面一個(gè)任務(wù)處理完成了,才會(huì)進(jìn)行處理。
而項(xiàng)目中還有數(shù)個(gè)定時(shí)任務(wù)。
解決法案
是初始一個(gè)定時(shí)任務(wù)執(zhí)行線程池
@Configuration
public class ScheduleConfig implements SchedulingConfigurer {
?
? ? @Override
? ? public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
? ? ? ? Method[] methods = BatchProperties.Job.class.getMethods();
? ? ? ? int defaultPoolSize = 10;
? ? ? ? int corePoolSize = 0;
? ? ? ? if (methods != null && methods.length > 0) {
? ? ? ? ? ? for (Method method : methods) {
? ? ? ? ? ? ? ? Scheduled annotation = method.getAnnotation(Scheduled.class);
? ? ? ? ? ? ? ? if (annotation != null) {
? ? ? ? ? ? ? ? ? ? corePoolSize++;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? if (defaultPoolSize > corePoolSize)
? ? ? ? ? ? ? ? corePoolSize = defaultPoolSize;
? ? ? ? }
? ? ? ? taskRegistrar.setScheduler(Executors.newScheduledThreadPool(corePoolSize));
?
? ? }
}再次測(cè)試,跟設(shè)置的間隔時(shí)間2秒一致。
執(zhí)行時(shí)間:::::Wed Nov 30 16:48:32 CST 2022
執(zhí)行時(shí)間:::::Wed Nov 30 16:48:34 CST 2022
執(zhí)行時(shí)間:::::Wed Nov 30 16:48:36 CST 2022
執(zhí)行時(shí)間:::::Wed Nov 30 16:48:38 CST 2022
定時(shí)任務(wù)@Scheduled入門
一個(gè)最簡(jiǎn)單的例子
啟動(dòng)類添加注解
@EnableScheduling // 開(kāi)啟定時(shí)任務(wù)

編寫(xiě)單線程demo

cron 表達(dá)式
/**
* cron 表達(dá)式
* 每2秒執(zhí)行一次
* @throws InterruptedException
*/
@Scheduled(cron = "0/2 * * * * *")
public void test() throws InterruptedException {
// 經(jīng)過(guò)測(cè)試,使用cron表達(dá)式,定時(shí)任務(wù)第二次會(huì)等待第一次執(zhí)行完畢再開(kāi)始!
Thread.sleep(5000L);
log.info("定時(shí)任務(wù)測(cè)試cron:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
}
fixedDelay
/**
* fixedDelay:
* 第一次執(zhí)行完畢才會(huì)執(zhí)行第二次,時(shí)間間隔變?yōu)榱?秒
* @throws InterruptedException
*/
@Scheduled(fixedDelay = 2000L)
public void test2() throws InterruptedException {
Thread.sleep(5000L);
log.info("定時(shí)任務(wù)測(cè)試fixedDelay:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
}

fixedRate
/**
* fixedRate:
* 每隔2秒就會(huì)執(zhí)行, 但是因?yàn)閱尉€程,所以在5秒后會(huì)輸出,間隔就是5秒
* @throws InterruptedException
*/
@Scheduled(fixedRate = 2000L)
public void test3() throws InterruptedException {
Thread.sleep(5000L);
log.info("定時(shí)任務(wù)測(cè)試fixedRate:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
}

如果是一起執(zhí)行這三個(gè)定時(shí)任務(wù),那么會(huì)一個(gè)一個(gè)的來(lái), 因?yàn)橹挥幸粋€(gè)線程.
多線程
/**
*
* @author GMaya
*/
@Configuration
@EnableAsync
public class ScheduleConfig {
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.setPoolSize(50); // 設(shè)置線程池大小
return taskScheduler;
}
}
如果只是加這一個(gè)配置類, 確實(shí)是使用了多線程, 每個(gè)定時(shí)任務(wù)都互相不影響.
但是一個(gè)線程第一次阻塞了,第二次就不行了,所以在定時(shí)任務(wù)上再加
@Async

就是說(shuō)你這次失敗了, 不要影響我下次的運(yùn)行

總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
springcloud之Feign、ribbon如何設(shè)置超時(shí)時(shí)間和重試機(jī)制
這篇文章主要介紹了springcloud之Feign、ribbon如何設(shè)置超時(shí)時(shí)間和重試機(jī)制,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08
新聞列表的分頁(yè)查詢java代碼實(shí)現(xiàn)
這篇文章主要為大家詳細(xì)介紹了新聞列表的分頁(yè)查詢java代碼實(shí)現(xiàn),感興趣的小伙伴們可以參考一下2016-08-08
java返回集合為null還是空集合及空集合的三種寫(xiě)法小結(jié)
這篇文章主要介紹了java返回集合為null還是空集合及空集合的三種寫(xiě)法小結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
Java簡(jiǎn)易抽獎(jiǎng)系統(tǒng)小項(xiàng)目
這篇文章主要為大家詳細(xì)介紹了Java簡(jiǎn)易抽獎(jiǎng)系統(tǒng)小項(xiàng)目,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01
Spring?boot配置綁定和配置屬性校驗(yàn)的方式詳解
這篇文章主要介紹了Spring?boot配置綁定和配置屬性校驗(yàn),SpringBoot 提供了2 種方式進(jìn)行配置綁定,即使用 @ConfigurationProperties 注解和使用 @Value 注解,需要的朋友可以參考下2022-05-05
idea啟動(dòng)spring項(xiàng)目中文亂碼的解決方法
本文主要介紹了idea啟動(dòng)spring項(xiàng)目中文亂碼,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01

