SpringBoot最簡(jiǎn)單的定時(shí)任務(wù)@Scheduler的使用及解讀
SpringBoot定時(shí)任務(wù)@Scheduler
Spring Boot 中一般來(lái)說(shuō)定時(shí)任務(wù)使用@Scheduler注解或者Quartz框架,或者自定義線程實(shí)現(xiàn),最簡(jiǎn)單的當(dāng)屬@Scheduler注解
- 依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>- 創(chuàng)建Application:
@SpringBootApplication
//此注解開啟異步定時(shí)任務(wù),必須要有
@EnableScheduling
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}- 創(chuàng)建任務(wù):
@Component
public class SpringJob {
//springboot掃描到這個(gè)注解就會(huì)按照定義的計(jì)劃去執(zhí)行任務(wù)
//cron是cron表達(dá)式,因?yàn)楹芎?jiǎn)單但是描述要話費(fèi)比較多的篇幅,所以略
@Scheduled(cron = "0/1 * * * * ?")
public void myJob(){
//任務(wù)處理邏輯
System.out.println(new Date() +"Spring Scheduler 執(zhí)行");
}
}- 啟動(dòng) Application:

上述是一個(gè)最簡(jiǎn)單的單job cron調(diào)度的實(shí)現(xiàn).
- @Scheduler中的參數(shù):
String cron() default ""; String zone() default ""; long fixedDelay() default -1; String fixedDelayString() default ""; long fixedRate() default -1; String fixedRateString() default ""; long initialDelay() default -1; String initialDelayString() default "";
String cron() default “”;接收一個(gè)cron表達(dá)式字符串,以cron表達(dá)式調(diào)度任務(wù) String zone() default “”;設(shè)置時(shí)區(qū),不設(shè)置的話cron就基于服務(wù)器所在的本地時(shí)區(qū) long fixedDelay() default -1;設(shè)置任務(wù)間隔時(shí)間(毫秒),就是任務(wù)結(jié)束后再過(guò)多久開始新的任務(wù) String fixedDelayString() default “”;同 long fixedDelay(),只是把參數(shù)從long改成string long fixedRate() default -1;設(shè)置任務(wù)每隔多久開啟 String fixedRateString() default “”;同 long fixedRate() 只是把參數(shù)從long改成string long initialDelay() default -1;第一次執(zhí)行延遲時(shí)間(啟動(dòng)后多久才開始任務(wù)) String initialDelayString() default “”;同 long initialDelay()
- spring boot 默認(rèn)開啟一個(gè)線程執(zhí)行任務(wù):
@Component
public class SpringJob {
@Scheduled(fixedRateString = "1000")
public void myJob2() throws InterruptedException {
System.out.println(new Date() +" job開啟");
Thread.sleep(2000);
System.out.println(new Date() +" job結(jié)束");
}
}
執(zhí)行結(jié)果:
Fri Jul 31 10:34:16 CST 2020 job開啟
Fri Jul 31 10:34:18 CST 2020 job結(jié)束
Fri Jul 31 10:34:18 CST 2020 job開啟
Fri Jul 31 10:34:20 CST 2020 job結(jié)束
Fri Jul 31 10:34:20 CST 2020 job開啟
Fri Jul 31 10:34:22 CST 2020 job結(jié)束
Fri Jul 31 10:34:22 CST 2020 job開啟
Fri Jul 31 10:34:24 CST 2020 job結(jié)束
Fri Jul 31 10:34:24 CST 2020 job開啟
Fri Jul 31 10:34:26 CST 2020 job結(jié)束
Fri Jul 31 10:34:26 CST 2020 job開啟
Fri Jul 31 10:34:28 CST 2020 job結(jié)束
Fri Jul 31 10:34:28 CST 2020 job開啟
Fri Jul 31 10:34:30 CST 2020 job結(jié)束設(shè)置的任務(wù)為每隔1秒中開啟一次,一次任務(wù)執(zhí)行時(shí)間是2秒,但是發(fā)現(xiàn)執(zhí)行的過(guò)程是,同一時(shí)間只有一個(gè)線程在執(zhí)行.也就是單線程執(zhí)行
- 現(xiàn)在執(zhí)行兩個(gè)job,單線程情況下,自然也是無(wú)法并發(fā)的:
@Component
public class SpringJob {
@Scheduled(fixedRateString = "2000")
public void myJob() throws InterruptedException {
System.out.println(new Date() +" job1開始");
Thread.sleep(10000);
System.out.println(new Date() +" job1結(jié)束");
}
@Scheduled(fixedRateString = "1000")
public void myJob2() throws InterruptedException {
System.out.println(new Date() +" job2開啟");
Thread.sleep(2000);
System.out.println(new Date() +" job2結(jié)束");
}
}
執(zhí)行結(jié)果:
Fri Jul 31 10:51:56 CST 2020 job1開始
Fri Jul 31 10:52:06 CST 2020 job1結(jié)束
Fri Jul 31 10:52:06 CST 2020 job2開啟
Fri Jul 31 10:52:08 CST 2020 job2結(jié)束
Fri Jul 31 10:52:08 CST 2020 job2開啟
Fri Jul 31 10:52:10 CST 2020 job2結(jié)束
Fri Jul 31 10:52:10 CST 2020 job1開始
Fri Jul 31 10:52:20 CST 2020 job1結(jié)束
Fri Jul 31 10:52:20 CST 2020 job2開啟
Fri Jul 31 10:52:22 CST 2020 job2結(jié)束
Fri Jul 31 10:52:22 CST 2020 job2開啟
Fri Jul 31 10:52:24 CST 2020 job2結(jié)束任務(wù)的每次執(zhí)行,無(wú)論是單個(gè)任務(wù)多次執(zhí)行,還是多個(gè)任務(wù)一次執(zhí)行,對(duì)于線程來(lái)說(shuō)都是一樣的,都需要開啟一個(gè)線程.有幾個(gè)線程就可以幾個(gè)任務(wù)(或者相同任務(wù)的多次)并發(fā)執(zhí)行
默認(rèn)情況下,scheduler只有一個(gè)線程
- 自定義線程池,添加一個(gè)配置類:
@Configuration
public class ScheduleConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(setExecutor());
}
@Bean
public Executor setExecutor() {
//設(shè)置線程個(gè)數(shù),這里我們?cè)O(shè)置5個(gè)(同一時(shí)間可以并行執(zhí)行5個(gè)線程)
return Executors.newScheduledThreadPool(5);
}
}- 此時(shí)執(zhí)行上方的單個(gè)任務(wù):
Fri Jul 31 10:55:18 CST 2020 job開啟
Fri Jul 31 10:55:20 CST 2020 job結(jié)束
Fri Jul 31 10:55:20 CST 2020 job開啟
Fri Jul 31 10:55:22 CST 2020 job結(jié)束
Fri Jul 31 10:55:22 CST 2020 job開啟
Fri Jul 31 10:55:24 CST 2020 job結(jié)束
Fri Jul 31 10:55:24 CST 2020 job開啟
Fri Jul 31 10:55:26 CST 2020 job結(jié)束
單個(gè)任務(wù)還是只能串行執(zhí)行.
- 執(zhí)行上方的兩個(gè)任務(wù):
Fri Jul 31 10:59:59 CST 2020 job2開啟
Fri Jul 31 10:59:59 CST 2020 job1開始
Fri Jul 31 11:00:01 CST 2020 job2結(jié)束
Fri Jul 31 11:00:01 CST 2020 job2開啟
Fri Jul 31 11:00:03 CST 2020 job2結(jié)束
Fri Jul 31 11:00:03 CST 2020 job2開啟
Fri Jul 31 11:00:05 CST 2020 job2結(jié)束
Fri Jul 31 11:00:05 CST 2020 job2開啟
Fri Jul 31 11:00:07 CST 2020 job2結(jié)束
Fri Jul 31 11:00:07 CST 2020 job2開啟
Fri Jul 31 11:00:09 CST 2020 job1結(jié)束
Fri Jul 31 11:00:09 CST 2020 job1開始
Fri Jul 31 11:00:09 CST 2020 job2結(jié)束
發(fā)現(xiàn)任務(wù)跟job1與job2之間是可以并發(fā)執(zhí)行的.但是對(duì)于job1的多次任務(wù),job2的多次任務(wù),都是串行執(zhí)行的.
現(xiàn)在線程池中有多個(gè)線程,job與job之間可以并發(fā),如何讓單個(gè)job的多次可以并發(fā)執(zhí)行,就需要@Async注解,此注解要用在job的方法上.@EnableAsync注解,此注解要在Application類上,此時(shí),job的多次執(zhí)行也可以并發(fā)執(zhí)行了.
@SpringBootApplication
@EnableScheduling
@EnableAsync
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@Component
public class SpringJob {
@Async
@Scheduled(fixedRateString = "2000")
public void myJob() throws InterruptedException {
System.out.println(new Date() + " job1開始");
Thread.sleep(10000);
System.out.println(new Date() + " job1結(jié)束");
}
@Scheduled(fixedRateString = "1000")
public void myJob2() throws InterruptedException {
System.out.println(new Date() + " job2開啟");
Thread.sleep(2000);
System.out.println(new Date() + " job2結(jié)束");
}
}
執(zhí)行結(jié)果:
Fri Jul 31 11:08:57 CST 2020 job2開啟
Fri Jul 31 11:08:57 CST 2020 job1開始
Fri Jul 31 11:08:59 CST 2020 job1開始
Fri Jul 31 11:08:59 CST 2020 job2結(jié)束
Fri Jul 31 11:08:59 CST 2020 job2開啟
Fri Jul 31 11:09:01 CST 2020 job1開始
Fri Jul 31 11:09:01 CST 2020 job2結(jié)束
Fri Jul 31 11:09:01 CST 2020 job2開啟
Fri Jul 31 11:09:03 CST 2020 job1開始
Fri Jul 31 11:09:03 CST 2020 job2結(jié)束
Fri Jul 31 11:09:03 CST 2020 job2開啟可以發(fā)現(xiàn)job1在前一次沒(méi)有執(zhí)行完時(shí),就已經(jīng)開始執(zhí)行了.
重要一點(diǎn)
自定線程池Configuration是為了啟用多線程,此時(shí)可以起到j(luò)ob1與job2之間的并發(fā)執(zhí)行,但是job1多次任務(wù)只能串行執(zhí)行,所以才增加了@Aysnc跟@EnableAsync注解.
@EnableAsync注解有兩個(gè)作用,1單線程變多線程,2 可以允許單個(gè)job多次運(yùn)行時(shí)并行執(zhí)行(需要再加@Async),如果已經(jīng)是多線程了,但是不加此注解,同一個(gè)job的多次執(zhí)行還是串行.
其實(shí)在使用@EnableAsync注解的時(shí)候,springboot會(huì)把自定義的configuration給覆蓋掉,即使在configuration中配置了單個(gè)線程,任務(wù)的并發(fā)也不會(huì)受到影響.所以推薦使用@EnableAsync來(lái)完成多線程配置再加@Aysnc來(lái)完成任務(wù)的并發(fā).
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- SpringBoot項(xiàng)目使用@Scheduled注解實(shí)現(xiàn)定時(shí)任務(wù)的方法
- SpringBoot整合ShedLock解決定時(shí)任務(wù)防止重復(fù)執(zhí)行的問(wèn)題
- SpringBoot項(xiàng)目如何使用多線程執(zhí)行定時(shí)任務(wù)
- SpringBoot最新定時(shí)任務(wù)的7種實(shí)現(xiàn)方案
- SpringBoot集成ShedLock實(shí)現(xiàn)分布式定時(shí)任務(wù)的示例代碼
- springboot定時(shí)任務(wù)不起作用問(wèn)題及解決
- 基于SpringBoot實(shí)現(xiàn)輕量級(jí)的動(dòng)態(tài)定時(shí)任務(wù)調(diào)度的方法
相關(guān)文章
Spring Boot 數(shù)據(jù)校驗(yàn)@Valid+統(tǒng)一異常處理的實(shí)現(xiàn)
這篇文章主要介紹了Spring Boot 數(shù)據(jù)校驗(yàn)@Valid+統(tǒng)一異常處理的實(shí)現(xiàn),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-04-04
springboot項(xiàng)目中mybatis-plus@Mapper注入失敗問(wèn)題
這篇文章主要介紹了springboot項(xiàng)目中mybatis-plus@Mapper注入失敗問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07
Spring?Boot整合Bootstrap的超詳細(xì)步驟
之前做前端開發(fā),在使用bootstrap的時(shí)候都是去官網(wǎng)下載,然后放到項(xiàng)目中,在頁(yè)面引用,下面這篇文章主要給大家介紹了關(guān)于Spring?Boot整合Bootstrap的超詳細(xì)步驟,需要的朋友可以參考下2023-05-05
Java中一個(gè)線程執(zhí)行死循環(huán)有什么后果
這篇文章主要為大家詳細(xì)介紹了Java中一個(gè)線程執(zhí)行死循環(huán)有什么后果,當(dāng)一個(gè)線程在執(zhí)行死循環(huán)時(shí)會(huì)影響另外一個(gè)線程嗎,下面為大家揭曉2016-05-05
可視化定時(shí)任務(wù)quartz集成解析全過(guò)程
在開發(fā)中有很多定時(shí)任務(wù)都不是寫死的而是可以人為配置并且寫到數(shù)據(jù)庫(kù)中的,下面這篇文章主要給大家介紹了關(guān)于可視化定時(shí)任務(wù)quartz集成解析的相關(guān)資料,需要的朋友可以參考下2022-10-10

