Spring?Boot使用Schedule實(shí)現(xiàn)定時(shí)任務(wù)的方法
0. 開(kāi)發(fā)環(huán)境
IDE:IntelliJ IDEA 2017.1 x64
jdk:1.8.0_91
Spring Boot:2.1.1.RELEASE
1. 簡(jiǎn)單定時(shí)任務(wù)
對(duì)于一些比較簡(jiǎn)單的定時(shí)任務(wù),比如固定時(shí)間間隔執(zhí)行固定方法,在標(biāo)準(zhǔn)Java方法上注解@Scheduled即可
package cn.wbnull.springbootdemo.schedule;
import cn.wbnull.springbootdemo.util.DateUtils;
import cn.wbnull.springbootdemo.util.LoggerUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class ScheduledTask {
@Scheduled(cron = "0/10 * * * * ?") //每10秒執(zhí)行一次
public void scheduledTaskByCorn() {
LoggerUtils.info("定時(shí)任務(wù)開(kāi)始 ByCorn:" + DateUtils.dateFormat());
scheduledTask();
LoggerUtils.info("定時(shí)任務(wù)結(jié)束 ByCorn:" + DateUtils.dateFormat());
}
@Scheduled(fixedRate = 10000) //每10秒執(zhí)行一次
public void scheduledTaskByFixedRate() {
LoggerUtils.info("定時(shí)任務(wù)開(kāi)始 ByFixedRate:" + DateUtils.dateFormat());
scheduledTask();
LoggerUtils.info("定時(shí)任務(wù)結(jié)束 ByFixedRate:" + DateUtils.dateFormat());
}
@Scheduled(fixedDelay = 10000) //每10秒執(zhí)行一次
public void scheduledTaskByFixedDelay() {
LoggerUtils.info("定時(shí)任務(wù)開(kāi)始 ByFixedDelay:" + DateUtils.dateFormat());
scheduledTask();
LoggerUtils.info("定時(shí)任務(wù)結(jié)束 ByFixedDelay:" + DateUtils.dateFormat());
}
private void scheduledTask() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
然后項(xiàng)目啟動(dòng)類(lèi)上增加注解@EnableScheduling,表示開(kāi)啟定時(shí)任務(wù)
package cn.wbnull.springbootdemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class SpringBootDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootDemoApplication.class, args);
}
}這里因?yàn)槲覀冊(cè)赟cheduledTask類(lèi)創(chuàng)建了三個(gè)定時(shí)任務(wù),@Scheduled默認(rèn)是不并發(fā)執(zhí)行的,因此我們先注釋掉其他,分別進(jìn)行測(cè)試。
1.1 @Scheduled(cron = “0/10 * * * * ?”)
package cn.wbnull.springbootdemo.schedule;
import cn.wbnull.springbootdemo.util.DateUtils;
import cn.wbnull.springbootdemo.util.LoggerUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class ScheduledTask {
@Scheduled(cron = "0/10 * * * * ?") //每10秒執(zhí)行一次
public void scheduledTaskByCorn() {
LoggerUtils.info("定時(shí)任務(wù)開(kāi)始 ByCorn:" + DateUtils.dateFormat());
scheduledTask();
LoggerUtils.info("定時(shí)任務(wù)結(jié)束 ByCorn:" + DateUtils.dateFormat());
}
private void scheduledTask() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}啟動(dòng)項(xiàng)目,運(yùn)行結(jié)果如下
[INFO][2019-02-18 16:08:40,095]||定時(shí)任務(wù)開(kāi)始 ByCorn:2019-02-18 16:08:40
[INFO][2019-02-18 16:08:45,097]||定時(shí)任務(wù)結(jié)束 ByCorn:2019-02-18 16:08:45
[INFO][2019-02-18 16:08:50,001]||定時(shí)任務(wù)開(kāi)始 ByCorn:2019-02-18 16:08:50
[INFO][2019-02-18 16:08:55,003]||定時(shí)任務(wù)結(jié)束 ByCorn:2019-02-18 16:08:55
[INFO][2019-02-18 16:09:00,002]||定時(shí)任務(wù)開(kāi)始 ByCorn:2019-02-18 16:09:00
[INFO][2019-02-18 16:09:05,004]||定時(shí)任務(wù)結(jié)束 ByCorn:2019-02-18 16:09:05
[INFO][2019-02-18 16:09:10,001]||定時(shí)任務(wù)開(kāi)始 ByCorn:2019-02-18 16:09:10
[INFO][2019-02-18 16:09:15,003]||定時(shí)任務(wù)結(jié)束 ByCorn:2019-02-18 16:09:15
[INFO][2019-02-18 16:09:20,001]||定時(shí)任務(wù)開(kāi)始 ByCorn:2019-02-18 16:09:20
[INFO][2019-02-18 16:09:25,002]||定時(shí)任務(wù)結(jié)束 ByCorn:2019-02-18 16:09:25
[INFO][2019-02-18 16:09:30,001]||定時(shí)任務(wù)開(kāi)始 ByCorn:2019-02-18 16:09:30
[INFO][2019-02-18 16:09:35,002]||定時(shí)任務(wù)結(jié)束 ByCorn:2019-02-18 16:09:35
我們?cè)俑南聅cheduledTask方法中線程休眠時(shí)間,使休眠時(shí)間大于定時(shí)任務(wù)間隔時(shí)間Thread.sleep(12000);,然后啟動(dòng)項(xiàng)目,查看運(yùn)行結(jié)果。
[INFO][2019-02-18 16:14:20,080]||定時(shí)任務(wù)開(kāi)始 ByCorn:2019-02-18 16:14:20
[INFO][2019-02-18 16:14:32,081]||定時(shí)任務(wù)結(jié)束 ByCorn:2019-02-18 16:14:32
[INFO][2019-02-18 16:14:40,001]||定時(shí)任務(wù)開(kāi)始 ByCorn:2019-02-18 16:14:40
[INFO][2019-02-18 16:14:52,002]||定時(shí)任務(wù)結(jié)束 ByCorn:2019-02-18 16:14:52
[INFO][2019-02-18 16:15:00,000]||定時(shí)任務(wù)開(kāi)始 ByCorn:2019-02-18 16:15:00
[INFO][2019-02-18 16:15:12,002]||定時(shí)任務(wù)結(jié)束 ByCorn:2019-02-18 16:15:12
我們可以看到,對(duì)于cron表達(dá)式 來(lái)說(shuō),如果業(yè)務(wù)代碼執(zhí)行時(shí)間小于定時(shí)任務(wù)間隔時(shí)間,那么定時(shí)任務(wù)每10秒執(zhí)行一次,且不受業(yè)務(wù)代碼影響,無(wú)論業(yè)務(wù)代碼執(zhí)行多久,定時(shí)任務(wù)都是10秒執(zhí)行一次;
如果業(yè)務(wù)代碼執(zhí)行時(shí)間大于定時(shí)任務(wù)間隔時(shí)間,因定時(shí)任務(wù)默認(rèn)不并發(fā),所以一直到業(yè)務(wù)代碼執(zhí)行完成的那個(gè)10秒,定時(shí)任務(wù)也是整10秒執(zhí)行一次,不受業(yè)務(wù)代碼影響。
注意:@Scheduled(cron = “0/10 * * * * ?”)控制的每10秒執(zhí)行一次的定時(shí)任務(wù),是每10秒整執(zhí)行一次,即一分鐘內(nèi),如果當(dāng)前秒數(shù)能夠整除10,則執(zhí)行定時(shí)任務(wù),或理解為每分鐘0秒開(kāi)始執(zhí)行,10秒后執(zhí)行下一次,執(zhí)行完一分鐘后,再?gòu)?秒開(kāi)始。即只會(huì)在10s,20s,30s…的時(shí)候執(zhí)行,如果配置定時(shí)任務(wù)@Scheduled(cron = “0/7 * * * * ?”)這種,則只會(huì)在0s,7s,14s…的時(shí)候執(zhí)行。
1.2 @Scheduled(fixedRate = 10000)
package cn.wbnull.springbootdemo.schedule;
import cn.wbnull.springbootdemo.util.DateUtils;
import cn.wbnull.springbootdemo.util.LoggerUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class ScheduledTask {
@Scheduled(fixedRate = 10000) //每10秒執(zhí)行一次
public void scheduledTaskByFixedRate() {
LoggerUtils.info("定時(shí)任務(wù)開(kāi)始 ByFixedRate:" + DateUtils.dateFormat());
scheduledTask();
LoggerUtils.info("定時(shí)任務(wù)結(jié)束 ByFixedRate:" + DateUtils.dateFormat());
}
private void scheduledTask() {
try {
Thread.sleep(12000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}啟動(dòng)項(xiàng)目,運(yùn)行結(jié)果如下
[INFO][2019-02-18 17:33:18,235]||定時(shí)任務(wù)開(kāi)始 ByFixedRate:2019-02-18 17:33:18
[INFO][2019-02-18 17:33:23,239]||定時(shí)任務(wù)結(jié)束 ByFixedRate:2019-02-18 17:33:23
[INFO][2019-02-18 17:33:28,191]||定時(shí)任務(wù)開(kāi)始 ByFixedRate:2019-02-18 17:33:28
[INFO][2019-02-18 17:33:33,195]||定時(shí)任務(wù)結(jié)束 ByFixedRate:2019-02-18 17:33:33
[INFO][2019-02-18 17:33:38,189]||定時(shí)任務(wù)開(kāi)始 ByFixedRate:2019-02-18 17:33:38
[INFO][2019-02-18 17:33:43,191]||定時(shí)任務(wù)結(jié)束 ByFixedRate:2019-02-18 17:33:43
[INFO][2019-02-18 17:33:48,184]||定時(shí)任務(wù)開(kāi)始 ByFixedRate:2019-02-18 17:33:48
[INFO][2019-02-18 17:33:53,186]||定時(shí)任務(wù)結(jié)束 ByFixedRate:2019-02-18 17:33:53
[INFO][2019-02-18 17:33:58,190]||定時(shí)任務(wù)開(kāi)始 ByFixedRate:2019-02-18 17:33:58
[INFO][2019-02-18 17:34:03,193]||定時(shí)任務(wù)結(jié)束 ByFixedRate:2019-02-18 17:34:03
我們?cè)俑南聅cheduledTask方法中線程休眠時(shí)間,使休眠時(shí)間大于定時(shí)任務(wù)間隔時(shí)間Thread.sleep(12000);,然后啟動(dòng)項(xiàng)目,查看運(yùn)行結(jié)果。
[INFO][2019-02-18 17:31:30,122]||定時(shí)任務(wù)開(kāi)始 ByFixedRate:2019-02-18 17:31:30
[INFO][2019-02-18 17:31:42,122]||定時(shí)任務(wù)結(jié)束 ByFixedRate:2019-02-18 17:31:42
[INFO][2019-02-18 17:31:42,123]||定時(shí)任務(wù)開(kāi)始 ByFixedRate:2019-02-18 17:31:42
[INFO][2019-02-18 17:31:54,123]||定時(shí)任務(wù)結(jié)束 ByFixedRate:2019-02-18 17:31:54
[INFO][2019-02-18 17:31:54,124]||定時(shí)任務(wù)開(kāi)始 ByFixedRate:2019-02-18 17:31:54
[INFO][2019-02-18 17:32:06,127]||定時(shí)任務(wù)結(jié)束 ByFixedRate:2019-02-18 17:32:06
[INFO][2019-02-18 17:32:06,127]||定時(shí)任務(wù)開(kāi)始 ByFixedRate:2019-02-18 17:32:06
[INFO][2019-02-18 17:32:18,134]||定時(shí)任務(wù)結(jié)束 ByFixedRate:2019-02-18 17:32:18
對(duì)于fixedRate 來(lái)說(shuō),如果業(yè)務(wù)代碼執(zhí)行時(shí)間小于定時(shí)任務(wù)間隔時(shí)間,那么定時(shí)任務(wù)每10秒執(zhí)行一次,且不受業(yè)務(wù)代碼影響,無(wú)論業(yè)務(wù)代碼執(zhí)行多久,定時(shí)任務(wù)都是10秒執(zhí)行一次;
如果業(yè)務(wù)代碼執(zhí)行時(shí)間大于定時(shí)任務(wù)間隔時(shí)間,則定時(shí)任務(wù)循環(huán)執(zhí)行。
1.3 @Scheduled(fixedDelay = 10000)
package cn.wbnull.springbootdemo.schedule;
import cn.wbnull.springbootdemo.util.DateUtils;
import cn.wbnull.springbootdemo.util.LoggerUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class ScheduledTask {
@Scheduled(fixedDelay = 10000) //每10秒執(zhí)行一次
public void scheduledTaskByFixedDelay() {
LoggerUtils.info("定時(shí)任務(wù)開(kāi)始 ByFixedDelay:" + DateUtils.dateFormat());
scheduledTask();
LoggerUtils.info("定時(shí)任務(wù)結(jié)束 ByFixedDelay:" + DateUtils.dateFormat());
}
private void scheduledTask() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}啟動(dòng)項(xiàng)目,運(yùn)行結(jié)果如下
[INFO][2019-02-18 17:45:30,784]||定時(shí)任務(wù)開(kāi)始 ByFixedDelay:2019-02-18 17:45:30
[INFO][2019-02-18 17:45:35,792]||定時(shí)任務(wù)結(jié)束 ByFixedDelay:2019-02-18 17:45:35
[INFO][2019-02-18 17:45:45,803]||定時(shí)任務(wù)開(kāi)始 ByFixedDelay:2019-02-18 17:45:45
[INFO][2019-02-18 17:45:50,812]||定時(shí)任務(wù)結(jié)束 ByFixedDelay:2019-02-18 17:45:50
[INFO][2019-02-18 17:46:00,814]||定時(shí)任務(wù)開(kāi)始 ByFixedDelay:2019-02-18 17:46:00
[INFO][2019-02-18 17:46:05,817]||定時(shí)任務(wù)結(jié)束 ByFixedDelay:2019-02-18 17:46:05
[INFO][2019-02-18 17:46:15,821]||定時(shí)任務(wù)開(kāi)始 ByFixedDelay:2019-02-18 17:46:15
[INFO][2019-02-18 17:46:20,825]||定時(shí)任務(wù)結(jié)束 ByFixedDelay:2019-02-18 17:46:20
[INFO][2019-02-18 17:46:30,829]||定時(shí)任務(wù)開(kāi)始 ByFixedDelay:2019-02-18 17:46:30
[INFO][2019-02-18 17:46:35,834]||定時(shí)任務(wù)結(jié)束 ByFixedDelay:2019-02-18 17:46:35
我們?cè)俑南聅cheduledTask方法中線程休眠時(shí)間,使休眠時(shí)間大于定時(shí)任務(wù)間隔時(shí)間Thread.sleep(12000);,然后啟動(dòng)項(xiàng)目,查看運(yùn)行結(jié)果。
[INFO][2019-02-18 17:47:06,871]||定時(shí)任務(wù)開(kāi)始 ByFixedDelay:2019-02-18 17:47:06
[INFO][2019-02-18 17:47:18,879]||定時(shí)任務(wù)結(jié)束 ByFixedDelay:2019-02-18 17:47:18
[INFO][2019-02-18 17:47:28,890]||定時(shí)任務(wù)開(kāi)始 ByFixedDelay:2019-02-18 17:47:28
[INFO][2019-02-18 17:47:40,896]||定時(shí)任務(wù)結(jié)束 ByFixedDelay:2019-02-18 17:47:40
[INFO][2019-02-18 17:47:50,903]||定時(shí)任務(wù)開(kāi)始 ByFixedDelay:2019-02-18 17:47:50
[INFO][2019-02-18 17:48:02,911]||定時(shí)任務(wù)結(jié)束 ByFixedDelay:2019-02-18 17:48:02
[INFO][2019-02-18 17:48:12,917]||定時(shí)任務(wù)開(kāi)始 ByFixedDelay:2019-02-18 17:48:12
[INFO][2019-02-18 17:48:24,924]||定時(shí)任務(wù)結(jié)束 ByFixedDelay:2019-02-18 17:48:24
對(duì)于fixedDelay 來(lái)說(shuō),不管業(yè)務(wù)代碼執(zhí)行時(shí)間與定時(shí)任務(wù)間隔時(shí)間熟長(zhǎng)熟短,定時(shí)任務(wù)都會(huì)等業(yè)務(wù)代碼執(zhí)行完成后再開(kāi)啟新一輪定時(shí)。
不過(guò),一般大家在使用定時(shí)任務(wù)時(shí),都是定時(shí)任務(wù)時(shí)間間隔大于業(yè)務(wù)代碼執(zhí)行時(shí)間。
1.4 多說(shuō)一點(diǎn)
對(duì)于固定時(shí)間執(zhí)行的定時(shí)任務(wù),比如每天凌晨4點(diǎn)執(zhí)行,只能使用cron表達(dá)式的方式
2. corn表達(dá)式
2.1 corn表達(dá)式格式
corn表達(dá)式格式:秒 分 時(shí) 日 月 星期 年(可選)
| 字段名 | 允許的值 | 允許的特殊字符 |
|---|---|---|
| 秒 | 0-59 | , - * / |
| 分 | 0-59 | , - * / |
| 時(shí) | 0-23 | , - * / |
| 日 | 1-31 | , - * ? / L W C |
| 月 | 1-12 或 JAN-DEC | , - * / |
| 星期 | 1-7 或 SUN-SAT | , - * ? / L C # |
| 年(可選) | 空 或 1970-2099 | , - * / |
釋義:
1、*:通配符,表示該字段可以接收任意值。
2、? :表示不確定的值,或不關(guān)心它為何值,僅在日期和星期中使用,當(dāng)其中一個(gè)設(shè)置了條件時(shí),另外一個(gè)用"?" 來(lái)表示"任何值"。
3、,:表示多個(gè)值,附加一個(gè)生效的值。
4、-:表示一個(gè)指定的范圍
5、/:指定一個(gè)值的增量值。例n/m表示從n開(kāi)始,每次增加m
6、L:用在日期表示當(dāng)月的最后一天,用在星期"L"單獨(dú)使用時(shí)就等于"7"或"SAT",如果和數(shù)字聯(lián)合使用表示該月最后一個(gè)星期X。例如,"0L"表示該月最后一個(gè)星期日。
7、W:指定離給定日期最近的工作日(周一到周五),可以用"LW"表示該月最后一個(gè)工作日。例如,"10W"表示這個(gè)月離10號(hào)最近的工作日
8、C:表示和calendar聯(lián)系后計(jì)算過(guò)的值。例如:用在日期中,"5C"表示該月第5天或之后包括calendar的第一天;用在星期中,"5C"表示這周四或之后包括calendar的第 一天。
9、#:表示該月第幾個(gè)星期X。例6#3表示該月第三個(gè)周五。
2.2 示例值
0 * * * * ? 每分鐘觸發(fā)
0 0 * * * ? 每小時(shí)整觸發(fā)
0 0 4 * * ? 每天凌晨4點(diǎn)觸發(fā)
0 15 10 * * ? 每天早上10:15觸發(fā)
*/5 * * * * ? 每隔5秒觸發(fā)
0 */5 * * * ? 每隔5分鐘觸發(fā)
0 0 4 1 * ? 每月1號(hào)凌晨4點(diǎn)觸發(fā)
0 0 4 L * ? 每月最后一天凌晨3點(diǎn)觸發(fā)
0 0 3 ? * L 每周星期六凌晨3點(diǎn)觸發(fā)
0 11,22,33 * * * ? 每小時(shí)11分、22分、33分觸發(fā)
3. 配置定時(shí)任務(wù)
對(duì)于上面那些簡(jiǎn)單的定時(shí)任務(wù),定時(shí)任務(wù)的corn表達(dá)式寫(xiě)死在代碼里,如果要改動(dòng)表達(dá)式,需要修改代碼,重新打包發(fā)布,比較麻煩。因此,我們可以把corn表達(dá)式配置在配置文件中,然后程序讀取配置,當(dāng)需要修改表達(dá)式時(shí),只需要修改配置文件即可。
application.yml增加配置
demo: corn: 0/11 * * * * ?
定時(shí)任務(wù)
package cn.wbnull.springbootdemo.schedule;
import cn.wbnull.springbootdemo.util.DateUtils;
import cn.wbnull.springbootdemo.util.LoggerUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class ScheduledTask {
@Scheduled(cron = "${demo.corn}")
public void scheduledTaskByConfig() {
LoggerUtils.info("定時(shí)任務(wù) ByConfig:" + DateUtils.dateFormat());
}
}啟動(dòng)項(xiàng)目,運(yùn)行結(jié)果如下
[INFO][2019-02-18 23:47:33,047]||定時(shí)任務(wù) ByConfig:2019-02-18 23:47:33
[INFO][2019-02-18 23:47:44,003]||定時(shí)任務(wù) ByConfig:2019-02-18 23:47:44
[INFO][2019-02-18 23:47:55,009]||定時(shí)任務(wù) ByConfig:2019-02-18 23:47:55
[INFO][2019-02-18 23:48:00,008]||定時(shí)任務(wù) ByConfig:2019-02-18 23:48:00
[INFO][2019-02-18 23:48:11,009]||定時(shí)任務(wù) ByConfig:2019-02-18 23:48:11
[INFO][2019-02-18 23:48:22,009]||定時(shí)任務(wù) ByConfig:2019-02-18 23:48:22
[INFO][2019-02-18 23:48:33,009]||定時(shí)任務(wù) ByConfig:2019-02-18 23:48:33
修改application.yml配置
demo: corn: 0/23 * * * * ?
啟動(dòng)項(xiàng)目,運(yùn)行結(jié)果如下
[INFO][2019-02-18 23:52:23,089]||定時(shí)任務(wù) ByConfig:2019-02-18 23:52:23
[INFO][2019-02-18 23:52:46,008]||定時(shí)任務(wù) ByConfig:2019-02-18 23:52:46
[INFO][2019-02-18 23:53:00,009]||定時(shí)任務(wù) ByConfig:2019-02-18 23:53:00
[INFO][2019-02-18 23:53:23,002]||定時(shí)任務(wù) ByConfig:2019-02-18 23:53:23
[INFO][2019-02-18 23:53:46,009]||定時(shí)任務(wù) ByConfig:2019-02-18 23:53:46
定時(shí)任務(wù)根據(jù)配置文件動(dòng)態(tài)變化。
4. 動(dòng)態(tài)修改定時(shí)任務(wù)
對(duì)于有些情況,我們需要在代碼中,通過(guò)方法動(dòng)態(tài)修改定時(shí)任務(wù)corn表達(dá)式
application.yml配置
demo: corn: 0/7 * * * * ? cornV2: 0/22 * * * * ?
新建ScheduledTaskV2.java
package cn.wbnull.springbootdemo.schedule;
import cn.wbnull.springbootdemo.util.DateUtils;
import cn.wbnull.springbootdemo.util.LoggerUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;
@Component
public class ScheduledTaskV2 implements SchedulingConfigurer {
@Value("${demo.corn}")
private String corn;
@Value("${demo.cornV2}")
private String cornV2;
private int tag = 0;
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
scheduledTaskRegistrar.addTriggerTask(() -> {
LoggerUtils.info("定時(shí)任務(wù)V2:" + DateUtils.dateFormat());
}, (triggerContext) -> {
CronTrigger cronTrigger;
if (tag % 2 == 0) {
LoggerUtils.info("定時(shí)任務(wù)V2動(dòng)態(tài)修改corn表達(dá)式:" + corn + "," + DateUtils.dateFormat());
cronTrigger = new CronTrigger(corn);
tag++;
} else {
LoggerUtils.info("定時(shí)任務(wù)V2動(dòng)態(tài)修改corn表達(dá)式:" + cornV2 + "," + DateUtils.dateFormat());
cronTrigger = new CronTrigger(cornV2);
tag++;
}
return cronTrigger.nextExecutionTime(triggerContext);
});
}
}
啟動(dòng)項(xiàng)目,運(yùn)行結(jié)果如下
[INFO][2019-02-19 00:19:49,011]||定時(shí)任務(wù)V2:2019-02-19 00:19:49
[INFO][2019-02-19 00:19:49,011]||定時(shí)任務(wù)V2動(dòng)態(tài)修改corn表達(dá)式:0/22 * * * * ?,2019-02-19 00:19:49
[INFO][2019-02-19 00:20:00,007]||定時(shí)任務(wù)V2:2019-02-19 00:20:00
[INFO][2019-02-19 00:20:00,007]||定時(shí)任務(wù)V2動(dòng)態(tài)修改corn表達(dá)式:0/7 * * * * ?,2019-02-19 00:20:00
[INFO][2019-02-19 00:20:07,006]||定時(shí)任務(wù)V2:2019-02-19 00:20:07
[INFO][2019-02-19 00:20:07,006]||定時(shí)任務(wù)V2動(dòng)態(tài)修改corn表達(dá)式:0/22 * * * * ?,2019-02-19 00:20:07
[INFO][2019-02-19 00:20:22,008]||定時(shí)任務(wù)V2:2019-02-19 00:20:22
[INFO][2019-02-19 00:20:22,008]||定時(shí)任務(wù)V2動(dòng)態(tài)修改corn表達(dá)式:0/7 * * * * ?,2019-02-19 00:20:22
[INFO][2019-02-19 00:20:28,010]||定時(shí)任務(wù)V2:2019-02-19 00:20:28
[INFO][2019-02-19 00:20:28,010]||定時(shí)任務(wù)V2動(dòng)態(tài)修改corn表達(dá)式:0/22 * * * * ?,2019-02-19 00:20:28
[INFO][2019-02-19 00:20:44,003]||定時(shí)任務(wù)V2:2019-02-19 00:20:44
[INFO][2019-02-19 00:20:44,003]||定時(shí)任務(wù)V2動(dòng)態(tài)修改corn表達(dá)式:0/7 * * * * ?,2019-02-19 00:20:44
[INFO][2019-02-19 00:20:49,004]||定時(shí)任務(wù)V2:2019-02-19 00:20:49
[INFO][2019-02-19 00:20:49,004]||定時(shí)任務(wù)V2動(dòng)態(tài)修改corn表達(dá)式:0/22 * * * * ?,2019-02-19 00:20:49
[INFO][2019-02-19 00:21:00,011]||定時(shí)任務(wù)V2:2019-02-19 00:21:00
[INFO][2019-02-19 00:21:00,011]||定時(shí)任務(wù)V2動(dòng)態(tài)修改corn表達(dá)式:0/7 * * * * ?,2019-02-19 00:21:00
[INFO][2019-02-19 00:21:07,011]||定時(shí)任務(wù)V2:2019-02-19 00:21:07
[INFO][2019-02-19 00:21:07,011]||定時(shí)任務(wù)V2動(dòng)態(tài)修改corn表達(dá)式:0/22 * * * * ?,2019-02-19 00:21:07
成功通過(guò)代碼動(dòng)態(tài)修改corn表達(dá)式且運(yùn)行結(jié)果正確。
5. 并發(fā)執(zhí)行定時(shí)任務(wù)
回到我們 1. 簡(jiǎn)單定時(shí)任務(wù) 中創(chuàng)建的三個(gè)定時(shí)任務(wù),當(dāng)時(shí)因?yàn)锧Scheduled默認(rèn)是不并發(fā)執(zhí)行的,所以我們先注釋掉了其他定時(shí)任務(wù),分別進(jìn)行的測(cè)試。
那我們實(shí)際開(kāi)發(fā)中,確實(shí)創(chuàng)建了多個(gè)定時(shí)任務(wù),且想并發(fā)執(zhí)行時(shí),該怎么做呢?
定時(shí)任務(wù)類(lèi)添加注解@EnableAsync,需并發(fā)執(zhí)行的定時(shí)任務(wù)方法添加注解@Async
新建定時(shí)任務(wù)類(lèi)ScheduledTaskV3
package cn.wbnull.springbootdemo.schedule;
import cn.wbnull.springbootdemo.util.DateUtils;
import cn.wbnull.springbootdemo.util.LoggerUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
@EnableAsync
public class ScheduledTaskV3 {
@Scheduled(cron = "0/7 * * * * ?")
@Async
public void scheduledTaskV1() {
LoggerUtils.info("定時(shí)任務(wù)V3,定時(shí)任務(wù)1開(kāi)始:" + DateUtils.dateFormat());
scheduledTask();
LoggerUtils.info("定時(shí)任務(wù)V3,定時(shí)任務(wù)1結(jié)束:" + DateUtils.dateFormat());
}
@Scheduled(cron = "0/10 * * * * ?")
@Async
public void scheduledTaskV2() {
LoggerUtils.info("定時(shí)任務(wù)V3,定時(shí)任務(wù)2開(kāi)始:" + DateUtils.dateFormat());
scheduledTask();
LoggerUtils.info("定時(shí)任務(wù)V3,定時(shí)任務(wù)2結(jié)束:" + DateUtils.dateFormat());
}
@Scheduled(cron = "0/22 * * * * ?")
@Async
public void scheduledTaskV3() {
LoggerUtils.info("定時(shí)任務(wù)V3,定時(shí)任務(wù)3開(kāi)始:" + DateUtils.dateFormat());
scheduledTask();
LoggerUtils.info("定時(shí)任務(wù)V3,定時(shí)任務(wù)3結(jié)束:" + DateUtils.dateFormat());
}
private void scheduledTask() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
啟動(dòng)項(xiàng)目,運(yùn)行結(jié)果如下
[INFO][2019-02-19 00:36:21,077]||定時(shí)任務(wù)V3,定時(shí)任務(wù)1開(kāi)始:2019-02-19 00:36:21
[INFO][2019-02-19 00:36:22,003]||定時(shí)任務(wù)V3,定時(shí)任務(wù)3開(kāi)始:2019-02-19 00:36:22
[INFO][2019-02-19 00:36:26,078]||定時(shí)任務(wù)V3,定時(shí)任務(wù)1結(jié)束:2019-02-19 00:36:26
[INFO][2019-02-19 00:36:27,006]||定時(shí)任務(wù)V3,定時(shí)任務(wù)3結(jié)束:2019-02-19 00:36:27
[INFO][2019-02-19 00:36:28,003]||定時(shí)任務(wù)V3,定時(shí)任務(wù)1開(kāi)始:2019-02-19 00:36:28
[INFO][2019-02-19 00:36:30,003]||定時(shí)任務(wù)V3,定時(shí)任務(wù)2開(kāi)始:2019-02-19 00:36:30
[INFO][2019-02-19 00:36:33,003]||定時(shí)任務(wù)V3,定時(shí)任務(wù)1結(jié)束:2019-02-19 00:36:33
[INFO][2019-02-19 00:36:35,004]||定時(shí)任務(wù)V3,定時(shí)任務(wù)1開(kāi)始:2019-02-19 00:36:35
[INFO][2019-02-19 00:36:35,005]||定時(shí)任務(wù)V3,定時(shí)任務(wù)2結(jié)束:2019-02-19 00:36:35
[INFO][2019-02-19 00:36:40,003]||定時(shí)任務(wù)V3,定時(shí)任務(wù)2開(kāi)始:2019-02-19 00:36:40
[INFO][2019-02-19 00:36:40,005]||定時(shí)任務(wù)V3,定時(shí)任務(wù)1結(jié)束:2019-02-19 00:36:40
[INFO][2019-02-19 00:36:42,001]||定時(shí)任務(wù)V3,定時(shí)任務(wù)1開(kāi)始:2019-02-19 00:36:42
[INFO][2019-02-19 00:36:44,003]||定時(shí)任務(wù)V3,定時(shí)任務(wù)3開(kāi)始:2019-02-19 00:36:44
[INFO][2019-02-19 00:36:45,004]||定時(shí)任務(wù)V3,定時(shí)任務(wù)2結(jié)束:2019-02-19 00:36:45
[INFO][2019-02-19 00:36:47,002]||定時(shí)任務(wù)V3,定時(shí)任務(wù)1結(jié)束:2019-02-19 00:36:47
[INFO][2019-02-19 00:36:49,002]||定時(shí)任務(wù)V3,定時(shí)任務(wù)1開(kāi)始:2019-02-19 00:36:49
[INFO][2019-02-19 00:36:49,004]||定時(shí)任務(wù)V3,定時(shí)任務(wù)3結(jié)束:2019-02-19 00:36:49
[INFO][2019-02-19 00:36:50,001]||定時(shí)任務(wù)V3,定時(shí)任務(wù)2開(kāi)始:2019-02-19 00:36:50
定時(shí)任務(wù)能夠并發(fā)執(zhí)行。
GitHub:https://github.com/dkbnull/SpringBootDemo
微信:https://mp.weixin.qq.com/s/qJZpCjcZYQWnmDkztiA_uQ
微博:https://weibo.com/ttarticle/p/show?id=2309404446645717696521
知乎:https://zhuanlan.zhihu.com/p/95813468
到此這篇關(guān)于Spring Boot使用Schedule實(shí)現(xiàn)定時(shí)任務(wù)的文章就介紹到這了,更多相關(guān)Spring Boot Schedule定時(shí)任務(wù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot中定時(shí)任務(wù)@Scheduled注解的使用解讀
- springboot定時(shí)任務(wù)@Scheduled執(zhí)行多次的問(wèn)題
- Springboot定時(shí)任務(wù)Scheduled重復(fù)執(zhí)行操作
- Spring boot基于ScheduledFuture實(shí)現(xiàn)定時(shí)任務(wù)
- Spring boot如何通過(guò)@Scheduled實(shí)現(xiàn)定時(shí)任務(wù)及多線程配置
- springboot schedule 解決定時(shí)任務(wù)不執(zhí)行的問(wèn)題
- SpringBoot2 task scheduler 定時(shí)任務(wù)調(diào)度器四種方式
- springboot集成schedule實(shí)現(xiàn)定時(shí)任務(wù)
相關(guān)文章
MyBatis測(cè)試報(bào)錯(cuò):Cannot?determine?value?type?from?string?&a
這篇文章主要給大家介紹了關(guān)于MyBatis測(cè)試報(bào)錯(cuò):Cannot?determine?value?type?from?string?'xxx'的解決辦法,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-02-02
詳解Java程序并發(fā)的Wait-Notify機(jī)制
這篇文章主要介紹了詳解Java程序并發(fā)的Wait-Notify機(jī)制,多線程并發(fā)是Java編程中的重要部分,需要的朋友可以參考下2015-07-07
springboot項(xiàng)目如何設(shè)置session的過(guò)期時(shí)間
這篇文章主要介紹了springboot項(xiàng)目如何設(shè)置session的過(guò)期時(shí)間,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01
Maven學(xué)習(xí)教程之搭建多模塊企業(yè)級(jí)項(xiàng)目
本篇文章主要介紹了Maven學(xué)習(xí)教程之搭建多模塊企業(yè)級(jí)項(xiàng)目 ,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10
解決Feign調(diào)用的GET參數(shù)傳遞的問(wèn)題
這篇文章主要介紹了解決Feign調(diào)用的GET參數(shù)傳遞的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
java動(dòng)態(tài)構(gòu)建數(shù)據(jù)庫(kù)復(fù)雜查詢教程
這篇文章主要介紹了java動(dòng)態(tài)構(gòu)建數(shù)據(jù)庫(kù)復(fù)雜查詢的實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2021-11-11
springboot中如何去整合shrio實(shí)例分享
這篇文章主要介紹了springboot中如何去整合shrio實(shí)例分享的相關(guān)資料,需要的朋友可以參考下2023-08-08

