当前位置:网站首页>上个厕所的功夫,就把定时任务的三种调度策略说得明明白白
上个厕所的功夫,就把定时任务的三种调度策略说得明明白白
2022-07-06 19:35:00 【刘水镜】
Spring Task 无疑是 Spring 环境下单机定时任务的首选。它用起来非常简单,功能也够用。
Spring Task 有三种模式,分别是:fixedDelay、cron 和 fixedRate。话不多说,我们先看代码:
@Slf4j
@Component
public class TimeTask {
private int[] people = {
6, 2, 3, 1};
private int count = 0;
@Scheduled(fixedDelay = 5000)
public void fixedDelayTask() throws InterruptedException {
if (count < 4) {
int timeConsuming = people[count];
log.info("fixedDelayTask-----第 {} 个人在 {} 开始如厕,耗时:{} 秒", count + 1,
formatTime(),
timeConsuming);
Thread.sleep(timeConsuming * 1000L);
count++;
}
}
@Scheduled(cron = "0/5 * * * * ? ")
public void cronTask() throws InterruptedException {
if (count < 4) {
int timeConsuming = people[count];
log.info("cronTask-----第 {} 个人在 {} 开始如厕,耗时:{} 秒", count + 1,
formatTime(),
timeConsuming);
Thread.sleep(timeConsuming * 1000L);
count++;
}
}
@Scheduled(fixedRate = 5000)
public void fixedRateTask() throws InterruptedException {
if (count < 4) {
int timeConsuming = people[count];
log.info("fixedRateTask-----第 {} 个人在 {} 开始如厕,耗时:{} 秒", count + 1,
formatTime(),
timeConsuming);
Thread.sleep(timeConsuming * 1000L);
count++;
}
}
private String formatTime() {
return LocalTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss"));
}
}
这三种模式的用法都很简单,使用方式也很类似。那么它们究竟有什么不同呢?下面我们通过一个五星级豪华公测的故事来说明一下。
故事背景
话说某地有一个五星级豪华厕所,大家都喜欢来这里如厕。因此坑位经常供不应求,需要排队如厕。一天,厕所外有四个人排队,每个人如厕需要的时间如下:
- 第一个人 6 秒钟
- 第二个人 2 秒钟
- 第三个人 3 秒钟
- 第四个人 1 秒钟
从第一个人开始如厕进行计时。
fixedDelay 模式
日志输出:
fixedDelayTask-----第 1 个人在 18:07:23 开始如厕,耗时:6 秒
fixedDelayTask-----第 2 个人在 18:07:34 开始如厕,耗时:2 秒
fixedDelayTask-----第 3 个人在 18:07:41 开始如厕,耗时:3 秒
fixedDelayTask-----第 4 个人在 18:07:49 开始如厕,耗时:1 秒
@Scheduled(fixedDelay = 5000)
厕所在该模式下有一个特点:每次用完厕所后,需要有 5 秒钟的厕所自洁时间,需要对厕所进行清洁消毒等工作,从而保证下次使用的时候依然干净卫生。执行情况如图所示:
- 第一个人在第 0 秒时开始如厕,6 秒后结束,厕所需要 5 秒钟的自洁时间;
- 第二个人在第 11 秒(6+5)时开始如厕,2 秒后结束,厕所需要 5 秒钟的自洁时间;
- 第三个人在第 18 秒(11+2+5)时开始如厕,3 秒后结束,厕所需要 5 秒钟的自洁时间;
- 第四个人在第 26 秒 (18+3+5)时开始如厕,1 秒后结束…
Cron 模式
日志输出:
cronTask-----第 1 个人在 18:09:15 开始如厕,耗时:6 秒
cronTask-----第 2 个人在 18:09:25 开始如厕,耗时:2 秒
cronTask-----第 3 个人在 18:09:30 开始如厕,耗时:3 秒
cronTask-----第 4 个人在 18:09:35 开始如厕,耗时:1 秒
@Scheduled(cron = "0/5 * * * * ? ")
在该模式下,厕所只在时间秒数 5 的整数倍时准许人员进入使用。因为通过严谨的科学分析,发现在秒数为 5 的整数倍时如厕体验更佳,所以只有当前时间秒数为 5 的整数倍时才可以进入。并且,五星级豪华公测升级设备,可以在如厕完成的瞬间完成自洁消毒,因此不再需要额外的自洁时间了,也提升了厕所利用率。执行情况如图所示:
- 第一个人在 18:09:15 时开始如厕,6 秒后(18:09:21)结束,下一个如厕吉时为 18:09:25;
- 第二个人在 18:09:25 时开始如厕,2 秒后(18:09:27)结束,下一个如厕吉时为 18:09:30;
- 第三个人在 18:09:30 时开始如厕,3 秒后(18:09:33)结束,下一个如厕吉时为 18:09:35;
- 第四个人在 18:09:35 时开始如厕,1 秒后(18:09:36)结束…
fixedRate 模式
日志输出:
fixedRateTask-----第 1 个人在 18:10:18 开始如厕,耗时:6 秒
fixedRateTask-----第 2 个人在 18:10:24 开始如厕,耗时:2 秒
fixedRateTask-----第 3 个人在 18:10:28 开始如厕,耗时:3 秒
fixedRateTask-----第 4 个人在 18:10:33 开始如厕,耗时:1 秒
@Scheduled(fixedRate = 5000)
经过长时间的大数据分析,得出一个结论——人的最佳如厕时长是 5 秒钟。所以在该模式下,人们如厕前,厕所会根据等待人数提前制定出如厕计划,即为每位等待者分配 5 秒钟如厕时间。但是有一个规则:当如厕者提前结束,那么下一个人仍然需要等够 5 秒钟;而当如厕者超时以后,待厕者可以在上一人完成时立即如厕。那么:
如厕计划如下:
- 第一个人:第 0 秒进入
- 第二个人:第 5 秒进入
- 第三个人:第 10 秒进入
- 第四个人:第 15 秒进入
根据故事背景中每个人如厕时间,实际情况如图所示:
- 第一个人在第 0 秒时,即 18:10:18 时开始如厕,6 秒后结束,超时,第二个人无缝如厕;
- 第二个人在第 6 秒(0+6)时,即 18:10:24 开始如厕,2 秒后结束,未超时,第三个人等待 2 秒,按计划时间如厕;
- 第三个人在第 10 秒(6+2+2)时,即 18:10:28 开始如厕,3 秒后结束,未超时,第四个人等待 2 秒按计划如厕;
- 第四个人在第 15 秒 (6+2+2+3+2)时,即 18:10:33 开始如厕,1 秒后结束…
Cron 表达式
Cron 模式是定时任务中最强大的触发策略,可以应对更多的情况。一个 Cron 表达式总共有 7 个元素,分别如下表所示:
时间单位 | 是否必填 | 取值范围 | 通配符 |
---|---|---|---|
秒 | 是 | 0-59 的整数 | , - * / 四个字符 |
分 | 是 | 0-59 的整数 | , - * / 四个字符 |
时 | 是 | 0-23 的整数 | , - * / 四个字符 |
日 | 是 | 1-31 的整数(需要考虑该月的具体天数) | ,- * ? / L W C 八个字符 |
月 | 是 | 1~12 的整数或者 JAN-DEC | , - * / 四个字符 |
周 | 是 | 1~7 的整数或者 SUN-SAT (1=SUN) | , - * ? / L C # 八个字符 |
年 | 否 | 1970~2099 | , - * / 四个字符 |
更多独家精彩内容尽在我的新书《Spring Boot趣味实战课》中。
边栏推荐
- How to analyze fans' interests?
- A complete tutorial for getting started with redis: problem location and optimization
- MySQL
- 杰理之发射端在接收端关机之后假死机【篇】
- Redis getting started complete tutorial: client management
- Redis introduction complete tutorial: client case analysis
- Unity webgl adaptive web page size
- ERROR: Could not find a version that satisfies the requirement xxxxx (from versions: none)解决办法
- The annual salary of general test is 15W, and the annual salary of test and development is 30w+. What is the difference between the two?
- [software test] the most complete interview questions and answers. I'm familiar with the full text. If I don't win the offer, I'll lose
猜你喜欢
Django database (SQLite) basic introductory tutorial
Utilisation de la promesse dans es6
Remember the problem analysis of oom caused by a Jap query
Redis入门完整教程:复制原理
MySQL is an optimization artifact to improve the efficiency of massive data query
NuScenes数据集关于Radar数据的统计
实施MES管理系统时,哪些管理点是需要注意的
Summary of basic debugging steps of S120 driver
从 1.5 开始搭建一个微服务框架——日志追踪 traceId
What are the applications and benefits of MES management system
随机推荐
Cloud Mail . NET Edition
[2022 national tournament simulation] polygon - computational geometry, binary answer, multiplication
Wireshark installation
What are the applications and benefits of MES management system
Cglib agent in agent mode
Detailed explanation of 19 dimensional integrated navigation module sinsgps in psins (initial assignment part)
tensorboard的使用
How to analyze fans' interests?
uniapp的表单验证
牛客编程题--必刷101之双指针篇
从零安装Redis
Change your posture to do operation and maintenance! GOPs 2022 Shenzhen station highlights first!
左程云 递归+动态规划
Detailed explanation of 19 dimensional integrated navigation module sinsgps in psins (time synchronization part)
杰理之发射端在接收端关机之后假死机【篇】
Left value, right value
Unity uses maskablegraphic to draw a line with an arrow
Have fun | latest progress of "spacecraft program" activities
又一百万量子比特!以色列光量子初创公司完成1500万美元融资
Redis getting started complete tutorial: replication configuration