Spring @Scheduler使用cron表达式时的执行问题详解
前言
SpringScheduler里有两个概念:任务(Task)和运行任务的框架(TaskExecutor/TaskScheduler)。TaskExecutor顾名思义,是任务的执行器,允许我们异步执行多个任务。TaskScheduler是任务调度器,来运行未来的定时任务。触发器Trigger可以决定定时任务是否该运行了,最常用的触发器是CronTrigger。Spring内置了多种类型的TaskExecutor和TaskScheduler,方便用户根据不同业务场景选择。
本文主要介绍了关于Spring@Scheduler使用cron表达式执行问题的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧
主要想弄清使用Spring@Schedulercron表达式时的两个问题:
- 同一定时任务,第二次触发时间到了,第一次还没有执行完成时会执行吗?
- 不同的定时任务,相互之间是否有影响?
结论写在前面:
- 同一定时任务,第二次触发时间到了,第一次还没有执行完成时会执行吗?不会,会等前一次执行完成才执行下一次
- 不同的定时任务,相互之间是否有影响?取决于可用的定时任务线程数,如果线程数足够则不会影响;如果可用定时任务线程数少于要执行定时任务数量,未能获取到线程的自然要等到有空闲线程时才能执行。
下面是实验过程。。。。。
使用Spring@Scheduler时,默认只有一个线程,针对上面的问题,设计了3个实验:
- 设置Scheduler为多线程,设置一个线程5秒执行一次,方法体为sleep8秒
- 使用Scheduler默认的单线程,设置两个线程都是5秒执行一次,一个sleep8秒,一个不sleep
- 设置Scheduler为多线程,设置两个线程都是5秒执行一次,一个sleep8秒,一个不sleep
实验一
设置Scheduler为多线程,设置一个线程5秒执行一次,方法体为sleep8秒:
@Scheduled(cron="*/5*****")
publicvoidtest1()throwsInterruptedException{
log.info("test1,5秒执行一次,每次执行sleep8s");
Thread.sleep(8000L);
}
结果:
2017-10-1117:49:45scheduler-1test1,5秒执行一次,每次执行sleep8
2017-10-1117:49:55scheduler-1test1,5秒执行一次,每次执行sleep8
2017-10-1117:50:05scheduler-1test1,5秒执行一次,每次执行sleep8
2017-10-1117:50:15scheduler-2test1,5秒执行一次,每次执行sleep8
2017-10-1117:50:25scheduler-2test1,5秒执行一次,每次执行sleep8
2017-10-1117:50:35scheduler-1test1,5秒执行一次,每次执行sleep8
结论:
@Scheduled使用cron表达式,设置为多线程时,同一任务前一次没有执行完成,不会执行下一次
实验二
使用Scheduler默认的单线程,设置两个线程都是5秒执行一次,一个sleep8秒,一个不sleep
如果test2每8秒执行一次,则为串行
@Scheduled(cron="*/5*****")
publicvoidtest1()throwsInterruptedException{
System.out.println("test1,5秒执行一次,每次执行sleep8s");
Thread.sleep(8000L);
}
@Scheduled(cron="*/5*****")
publicvoidtest2(){
System.out.println("test2,5秒执行一次,不sleep");
}
执行结果:
2017-10-1117:17:35test2,5秒执行一次,不sleep
2017-10-1117:17:35test1,5秒执行一次,每次执行sleep8s
2017-10-1117:17:43test2,5秒执行一次,不sleep
2017-10-1117:17:45test1,5秒执行一次,每次执行sleep8s
2017-10-1117:17:53test2,5秒执行一次,不sleep
2017-10-1117:17:55test2,5秒执行一次,不sleep
2017-10-1117:17:55test1,5秒执行一次,每次执行sleep8s
2017-10-1117:18:03test2,5秒执行一次,不sleep
2017-10-1117:18:05test2,5秒执行一次,不sleep
2017-10-1117:18:05test1,5秒执行一次,每次执行sleep8s
2017-10-1117:18:13test2,5秒执行一次,不sleep
2017-10-1117:18:15test1,5秒执行一次,每次执行sleep8s
2017-10-1117:18:23test2,5秒执行一次,不sleep
2017-10-1117:18:25test1,5秒执行一次,每次执行sleep8s
对比期望执行时间:
| 执行次数 | task | 期望执行时间 | 实际执行时间 |
|---|---|---|---|
| 1 | task1 | 17:17:35 | 17:17:35 |
| 1 | task2 | 17:17:35 | 17:17:35 |
| 2 | task1 | 17:17:40 | 17:17:43 |
| 2 | task2 | 17:17:40 | 17:17:45 |
结论:
@Scheduled使用cron表达式,配置为一个线程时,不同定时任务是串行执行,且上次没有执行完时不会执行下次
实验三
设置Scheduler为多线程,设置两个线程都是5秒执行一次,一个sleep8秒,一个不sleep
@Scheduled(cron="*/5*****")
publicvoidtest1()throwsInterruptedException{
log.info("test1,5秒执行一次,每次执行sleep8s");
Thread.sleep(8000L);
}
@Scheduled(cron="*/5*****")
publicvoidtest2(){
log.info("test2,5秒执行一次,不sleep");
}
结果:
2017-10-1118:12:40scheduler-2test2,5秒执行一次,不sleep
2017-10-1118:12:40scheduler-1test1,5秒执行一次,每次执行sleep8s
2017-10-1118:12:45scheduler-2test2,5秒执行一次,不sleep
2017-10-1118:12:50scheduler-1test1,5秒执行一次,每次执行sleep8s
2017-10-1118:12:50scheduler-2test2,5秒执行一次,不sleep
2017-10-1118:12:55scheduler-2test2,5秒执行一次,不sleep
2017-10-1118:13:00scheduler-1test1,5秒执行一次,每次执行sleep8s
对比期望执行时间:
| 执行次数 | task | 期望执行时间 | 实际执行时间 |
|---|---|---|---|
| 1 | task1 | 18:12:40 | 18:12:40 |
| 1 | task2 | 18:12:40 | 18:12:40 |
| 2 | task1 | 18:12:45 | 18:12:50 |
| 2 | task2 | 18:12:45 | 18:12:45 |
结论:
@Scheduled使用cron表达式,配置为多线程时,不同定时任务不是串行执行,且上次没有执行完时不会执行下次
设置定时任务为多线程
这里用的是springboot:
@Configuration
publicclassScheduleConfig{
@Bean
publicThreadPoolTaskSchedulerthreadPoolTaskScheduler(){
ThreadPoolTaskSchedulerscheduler=newThreadPoolTaskScheduler();
scheduler.setPoolSize(3);
scheduler.setThreadNamePrefix("scheduler-");
returnscheduler;
}
}
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。