javascript
Spring定时任务注解@Scheduled+@EnableAsync用法详解(简单说明+应用场景+demo源代码+执行过程分析)
@Scheduled 由Spring定義,用于將方法設(shè)置為調(diào)度任務(wù),可實現(xiàn)方法的周期或定時執(zhí)行。想單獨使用Scheduling,需引入spring-context這個依賴。spring-boot-starter-web已經(jīng)集成了spring-context,所以可以直接使用Scheduling模塊(我使用的 SpringBoo t版本為 2.2.4.RELEASE)。
1.Demo走起
話不多說,先寫一個小Demo讓定時任務(wù)跑起來,然后再一步步添枝加葉層層深入。兩個注解【@EnableScheduling + @Scheduled】實現(xiàn)起步:
// 第一個注解@EnableScheduling @EnableScheduling @SpringBootApplication public class SBApplication implements ApplicationRunner {// ApplicationRunner 和 CommandLineRunner 可用于數(shù)據(jù)配置和預(yù)處理 參數(shù)類型不一樣public static void main(String[] args) {SpringApplication.run(SBApplication.class, args);}@Beanpublic CommandLineRunner commandLineRunner(ApplicationContext ctx) {return args -> {System.out.println("Let's inspect the beans provided by Spring Boot:");String[] beanNames = ctx.getBeanDefinitionNames();Arrays.sort(beanNames);/** for (String name : beanNames) { System.out.println(name); }*/};}@Overridepublic void run(ApplicationArguments args) throws Exception {/* 可以在springBoot啟動時執(zhí)行預(yù)處理程序 */System.out.println("啟動時就打印的數(shù)據(jù)!");} } // 第二個注解 @Scheduled @Component public class Scheduler {@Scheduled(fixedRate = 1000, initialDelay = 3000)public void fixedDelay() {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");String dateString = sdf.format(new Date());System.out.println(dateString);} }Demo實現(xiàn)的是項目啟動3s后每秒輸出當前時間,日志是誠實的…
2021-06-24 15:18:06.798 INFO 16108 --- [)-192.168.0.108] o.s.web.servlet.DispatcherServlet : Completed initialization in 5 ms 2021-06-24 15:18:09.559 2021-06-24 15:18:10.559 2021-06-24 15:18:11.558 2021-06-24 15:18:12.558 2021-06-24 15:18:13.558 2021-06-24 15:18:14.558 2021-06-24 15:18:15.5582.@Scheduled用法
// 先看看源碼 spring版本 5.2.3.RELEASE @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Repeatable(Schedules.class) public @interface Scheduled {String CRON_DISABLED = "-";String cron() default "";String zone() default "";long fixedDelay() default -1L;String fixedDelayString() default "";long fixedRate() default -1L;String fixedRateString() default "";long initialDelay() default -1L;String initialDelayString() default ""; }注解說明:
- @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}):表示@Schduled可以被使用在方法和注解上。
- @Retention(RetentionPolicy.RUNTIME):表示@Schduled的生命周期是在程序運行時。
- @Repeatable(Schedules.class):表示@Schduled可以被在同一個地方重復(fù)使用多次,參數(shù)存放在Schedules類中(我們可以點進去看Schedules類,發(fā)現(xiàn)里面有一個Scheduled數(shù)組對象,用來保存多個Scheduled的配置)。
屬性說明:
- String CRON_DISABLED:定時禁用標志。
- String cron():定義定時執(zhí)行時間,默認值為空字符串,表示該值無效。
- String zone():定義時區(qū),默認值為空字符串。
- long fixedDelay():定義任務(wù)下次開始執(zhí)行的間隔時間,從上一次任務(wù)執(zhí)行完成開始計算,單位毫秒。默認值-1L,表示該值設(shè)置無效。
- String fixedDelayString():定義任務(wù)下次開始執(zhí)行的間隔時間,從上一次任務(wù)執(zhí)行完成開始計算,單位毫秒。與fixedDelay不同只在于值的格式。默認值"",表示該值設(shè)置無效。
- long fixedRate():定義每兩次任務(wù)的間隔頻率,從上一次任務(wù)開始執(zhí)行開始計算,單位毫秒。默認值-1L,表示該值無效。
- String fixedRateString():定義每兩次任務(wù)的間隔頻率,從上一次任務(wù)開始執(zhí)行開始計算,單位毫秒。與fixedRate不同只在于值的格式。默認值為空字符串,表示該值無效。
- long initialDelay():定義第一次執(zhí)行的延遲執(zhí)行時間,單位秒。默認值-1L,表示沒有延遲。
- String initialDelayString():定義第一次執(zhí)行的延遲執(zhí)行時間,與initialDelayDelay()不同在于這里使用表達式,而不是以秒為單位。默認值為空字符串,表示沒有延遲。
特別注意:
我們要區(qū)分fixedDelay和fixedRate的不同,前者是當前方法執(zhí)行完畢后加上間隔時間再去執(zhí)行方法,后者不管任務(wù)是否執(zhí)行完畢間隔時間一到就會再次執(zhí)行方法。
3.cron
前面的demo實現(xiàn)的是簡單的延時和頻率執(zhí)行。使用cron可以實現(xiàn)定時定頻執(zhí)行。這里的cron跟Linux上的cron是不同的,Linux上的表達式?jīng)]有秒,大家要注意。
cron表達式是一個字符串,字符串以5或6個空格隔開,分為6或7個域,每一個域代表一個含義,由于年份非必填所以cron有如下兩種語法格式:
每一個域可出現(xiàn)的字符如下:
含義:
- *:表示匹配該域的任意值,假如在Minutes域使用*, 即表示每分鐘都會觸發(fā)事件。
- ?:只能用在DayofMonth和DayofWeek兩個域。它也匹配域的任意值,但實際不會。因為DayofMonth和 DayofWeek會相互影響。例如想在每月的20日觸發(fā)調(diào)度,不管20日到底是星期幾,則只能使用如下寫法: 13 13 15 20 * ?, 其中最后一位只能用?,而不能使用*,如果使用*表示不管星期幾都會觸發(fā),實際上并不是這樣。
- -:表示范圍,例如在Minutes域使用5-20,表示從5分到20分鐘每分鐘觸發(fā)一次。
- /:表示起始時間開始觸發(fā),然后每隔固定時間觸發(fā)一次,例如在Minutes域使用5/20,則意味著5分鐘觸發(fā)一次,而25,45等分別觸發(fā)一次。
- ,:表示列出枚舉值值。例如:在Minutes域使用5,20,則意味著在5和20分每分鐘觸發(fā)一次。
- L:表示最后,只能出現(xiàn)在DayofWeek和DayofMonth域,如果在DayofWeek域使用5L,意味著在最后的一個星期四觸發(fā)。
- W:表示有效工作日(周一到周五),只能出現(xiàn)在DayofMonth域,系統(tǒng)將在離指定日期的最近的有效工作日觸發(fā)事件。例如:在 DayofMonth使用5W,如果5日是星期六,則將在最近的工作日:星期五,即4日觸發(fā)。如果5日是星期天,則在6日(周一)觸發(fā);如果5日在星期一 到星期五中的一天,則就在5日觸發(fā)。另外一點,W的最近尋找不會跨過月份。
- LW:這兩個字符可以連用,表示在某個月最后一個工作日,即最后一個星期五。
- #:用于確定每個月第幾個星期幾,只能出現(xiàn)在DayofMonth域。例如在4#2,表示某月的第二個星期三。
舉幾個例子【這里是舉一反三的環(huán)節(jié)】 😃
- 每隔5秒執(zhí)行一次:*/5 * * * * ?
- 每隔1分鐘執(zhí)行一次:0 */1 * * * ? 【如果秒用 * 這樣就是每分每秒都執(zhí)行】
- 每天23點執(zhí)行一次:0 0 23 * * ? 【如果前面的兩個0 用了 * 那就是23點的每分每秒都執(zhí)行】
- 每月最后一天23點執(zhí)行一次:0 0 23 L * ?
- 每周星期天凌晨1點實行一次:0 0 1 ? * L
- 每天的0點、13點、18點、21點都執(zhí)行一次:0 0 0,13,18,21 * * ?
- 表示在每月的1日的凌晨2點調(diào)度任務(wù):0 0 2 1 * ? *
- 表示周一到周五每天上午10:15執(zhí)行作業(yè):0 15 10 ? * MON-FRI
- 表示2002-2006年的每個月的最后一個星期五上午10:15執(zhí)行:0 15 10 ? 6L 2002-2006
注意:由于"月份中的日期"和"星期中的日期"這兩個元素互斥的,必須要對其中一個設(shè)置?
總結(jié)
以上是生活随笔為你收集整理的Spring定时任务注解@Scheduled+@EnableAsync用法详解(简单说明+应用场景+demo源代码+执行过程分析)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Neo4j【付诸实践 01】Spring
- 下一篇: 【Linux部署】第一次部署ZooKee