Spring boot定时任务
开启定时任务
主启动类上添加@EnableScheduling
@SpringBootApplication @EnableScheduling public class Application {
public static void main(String[] args) { SpringApplication.run(Application.class, args); }
}
新建定时任务类
@Component
public class HelloTask {@Scheduled(cron ="0 */1 * * * ?") public void task1(){ String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); System.out.println("task1 "+date); } //每3秒执行一次 @Scheduled(fixedDelay = 3000) public void task2(){ String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); System.out.println("task2 "+date); } //容器启动后,延迟10秒后再执行一次定时器,以后每10秒再执行一次该定时器。 @Scheduled(initialDelay = 10000, fixedRate = 10000) public void task3(){ String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); System.out.println("task3 "+date); }
}
注意一定要把定时任务加入到容器中@Component不可少
Scheduled
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Schedules.class)
public @interface Scheduled {String CRON_DISABLED = ScheduledTaskRegistrar.CRON_DISABLED;
// 通过cron表达式的方式设置执行规则
String cron() default "";String zone() default "";
// 首次执行结束后延迟 fixedDelay 毫秒再次执行
long fixedDelay() default -1;String fixedDelayString() default "";
// 首次开始后延迟 fixedRate 毫秒再次执行,如果任务耗时超过 fixedRate 等任务结束后立即执行
long fixedRate() default -1;String fixedRateString() default "";
// 首次执行前延迟 initialDelay 毫秒
long initialDelay() default -1;String initialDelayString() default "";
}
fixedDelay与fixedRate对比
fixedDelay
@Scheduled(fixedDelay = 3000)
public void task2() throws InterruptedException {
String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
log.info("task2 " + date);
Thread.sleep(6000);
}
2024-04-06 17:02:40.692 INFO 151080 --- [ scheduling-1] com.lxw.station.task.HelloTask : task2 2024-04-06 17:02:40
2024-04-06 17:02:49.693 INFO 151080 --- [ scheduling-1] com.lxw.station.task.HelloTask : task2 2024-04-06 17:02:49
2024-04-06 17:02:58.695 INFO 151080 --- [ scheduling-1] com.lxw.station.task.HelloTask : task2 2024-04-06 17:02:58
2024-04-06 17:03:07.696 INFO 151080 --- [ scheduling-1] com.lxw.station.task.HelloTask : task2 2024-04-06 17:03:07
2024-04-06 17:03:16.698 INFO 151080 --- [ scheduling-1] com.lxw.station.task.HelloTask : task2 2024-04-06 17:03:16
2024-04-06 17:03:25.701 INFO 151080 --- [ scheduling-1] com.lxw.station.task.HelloTask : task2 2024-04-06 17:03:25
2024-04-06 17:03:34.702 INFO 151080 --- [ scheduling-1] com.lxw.station.task.HelloTask : task2 2024-04-06 17:03:34
可以看出@Scheduled(fixedDelay = 3000)表示执行完第一次后延迟3000毫秒再次执行
fixedRate
@SneakyThrows
@Scheduled(fixedRate = 3000)
public void task4() {
String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
log.info("task4 " + date);
Thread.sleep(6000);
}
2024-04-06 17:06:14.597 INFO 35892 --- [ scheduling-1] com.lxw.station.task.HelloTask : task4 2024-04-06 17:06:14
2024-04-06 17:06:20.598 INFO 35892 --- [ scheduling-1] com.lxw.station.task.HelloTask : task4 2024-04-06 17:06:20
2024-04-06 17:06:26.599 INFO 35892 --- [ scheduling-1] com.lxw.station.task.HelloTask : task4 2024-04-06 17:06:26
2024-04-06 17:06:32.600 INFO 35892 --- [ scheduling-1] com.lxw.station.task.HelloTask : task4 2024-04-06 17:06:32
2024-04-06 17:06:38.600 INFO 35892 --- [ scheduling-1] com.lxw.station.task.HelloTask : task4 2024-04-06 17:06:38
2024-04-06 17:06:44.617 INFO 35892 --- [ scheduling-1] com.lxw.station.task.HelloTask : task4 2024-04-06 17:06:44
2024-04-06 17:06:50.617 INFO 35892 --- [ scheduling-1] com.lxw.station.task.HelloTask : task4 2024-04-06 17:06:50
2024-04-06 17:06:56.618 INFO 35892 --- [ scheduling-1] com.lxw.station.task.HelloTask : task4 2024-04-06 17:06:56
2024-04-06 17:07:02.618 INFO 35892 --- [ scheduling-1] com.lxw.station.task.HelloTask : task4 2024-04-06 17:07:02
2024-04-06 17:07:08.618 INFO 35892 --- [ scheduling-1] com.lxw.station.task.HelloTask : task4 2024-04-06 17:07:08
2024-04-06 17:07:14.619 INFO 35892 --- [ scheduling-1] com.lxw.station.task.HelloTask : task4 2024-04-06 17:07:14
2024-04-06 17:07:20.619 INFO 35892 --- [ scheduling-1] com.lxw.station.task.HelloTask : task4 2024-04-06 17:07:20
fixedRate = 3000表示第一次执行开始后3000毫秒再次执行,如果3000毫秒没有执行完成,执行完成后立即执行第二次,从日子可以看出首次执行开始时间2024-04-06 17:06:14,执行耗时6000毫秒,执行结束时间也就是2024-04-06 17:06:20,接着立即执行第二次
cron表达式
结构
cron表达式是一个字符串,分为6或7个域(最后一位年,非必填),每两个域之间用空格分隔,
其语法格式为:“秒域 分域 时域 日域 月域 周域 年域”
取值范围
域名 | 可取值 | 可取符号(仅列部分常用) |
---|---|---|
秒域 | 0 | * - , / |
分域 | 059的整数 | * - , / |
时域 | 0 | * - , / |
日域 | 131的整数 | * - , / ? L W |
月域 | 112的整数或JANDEC | * - , / |
周域 | 17的整数或SUNSAT | * - , / ? L # |
年域 | 1970~2099的整数 | * - , / |
特殊字符说明
* | 匹配任意值。 | 在字段月中,*表示每个月。 |
---|---|---|
, | 列出枚举值。 | 在字段分钟中,5,20表示分别在5分钟和20分钟触发一次。 |
- | 指定范围。 | 在字段分钟中,5-20表示从5分钟到20分钟之间每隔一分钟触发一次。 |
/ | 指定数值的增量。 | 在字段分钟中,0/15表示从第0分钟开始,每15分钟。在字段分钟中3/20表示从第3分钟开始,每20分钟。 |
? | 不指定值,仅用于日期和星期。 | 当字段日期或星期其中之一被指定了值以后,为了避免冲突,需要将另一个字段的值设为?。 |
L | 单词Last的首字母,表示最后一天,仅字段日期和星期支持该字符。 重要:指定L字符时,避免指定列表或范围,否则会导致逻辑问题。 | 在日期中,L表示某个月的最后一天。在星期中,L表示一个星期的最后一天,也就是星期六。 如果在L前有具体的内容,例如,在字段星期中的6L表示这个月的最后一个星期五。 |
W | 除周末以外的有效工作日,在离指定日期的最近的有效工作日触发事件。W字符寻找最近有效工作日时不会跨过当前月份,连用字符LW时表示为指定月份的最后一个工作日。 | 在日期中5W,如果5日是星期六,则将在最近的工作日星期五,即4日触发。如果5日是星期天,则将在最近的工作日星期一,即6日触发;如果5日在星期一到星期五中的一天,则就在5日触发。 |
# | 确定每个月的第几个星期几。 | 在字段星期中,4#2表示某月的第二个星期四。 |
常例
表达式 | 意义 |
---|---|
每隔5秒钟执行一次 | */5 * * * * ? |
每隔1分钟执行一次 | 0 * /1 * * * ? |
每天1点执行一次 | 0 0 1 * * ? |
每天23点55分执行一次 | 0 55 23 * * ? |
每月最后一天23点执行一次 | 0 0 23 L * ? |
每周六8点执行一次 | 0 0 8 ? * L |
每月最后一个周五,每隔2小时执行一次 | 0 0 */2 ? * 6L |
每月的第三个星期五上午10:15执行一次 | 0 15 10 ? * 5#3 |
在每天下午2点到下午2:05期间的每1分钟执行 | 0 0-5 14 * * ? |
表示周一到周五每天上午10:15执行 | 0 15 10 ? * 2-6 |
每个月的最后一个星期五上午10:15执行 | 0 15 10 ? * 6L |
每天上午10点,下午2点,4点执行一次 | 0 0 10,14,16 * * ? |
朝九晚五工作时间内每半小时执行一次 | 0 0/30 9-17 * * ? |
每个星期三中午12点执行一次 | 0 0 12 ? * 4 |
每年三月的星期三的下午2:10和2:44各执行一次 | 0 10,44 14 ? 3 4 |
每月的第三个星期五上午10:15执行一次 | 0 15 10 ? * 6#3 |
每月一日凌晨2点30执行一次 | 0 30 2 1 * ? |
每分钟的第10秒与第20秒都会执行 | 10,20 * * * * ? |
每月的第2个星期的周5,凌晨执行 | 0 0 0 ? * 6#2 |