目录
概述
本篇文章将讨论如何在spring中使用@Scheduled注解,以及可能引发的异常。
如果要使用@Scheduled注解,有两个原则需要遵守。
首先,方法的返回时void,如果定义了返回值,那么此返回值也将被忽略。
其次,方法不接受参数传递。
启用此注解
我们只需要在SpringConfig上额外增加@EnableScheduling注解即可。
@Configuration
@EnableScheduling
public class SpringConfig {
...
}
定时任务 fix delay
在这种情况下,下一次的执行是在上一次执行完成之后再加上fixedDelay的时间。计时器保证在第一次任务执行介绍后开始计时。
@Scheduled(fixedDelay = 1000)
public void scheduleFixedDelayTask() {
System.out.println(
"Fixed delay task - " + System.currentTimeMillis() / 1000);
}
定时任务 fix rate
和fix delay不同,fix rate保证每一次的执行都是相互独立的,第一次是否执行结束不影响第二次的执行。
但是,默认情况下,任务不会并行执行。因此第二次执行一定会等到第一次执行结束后才开始执行。
@Scheduled(fixedRate = 1000)
public void scheduleFixedRateTask() {
System.out.println(
"Fixed rate task - " + System.currentTimeMillis() / 1000);
}
只有增加@EnableAsync以及@Async注解后会开启并行执行,这样的话,按照下面的配置。方法会每隔一秒执行一次。
@EnableAsync
public class ScheduledFixedRateExample {
@Async
@Scheduled(fixedRate = 1000)
public void scheduleFixedRateTaskAsync() throws InterruptedException {
System.out.println(
"Fixed rate task async - " + System.currentTimeMillis() / 1000);
Thread.sleep(2000);
}
}
定时任务 initial delay
通过设置initialDelay,我们同时可以设置定时任务的初试延迟。
@Scheduled(fixedDelay = 1000, initialDelay = 1000)
public void scheduleFixedRateWithInitialDelayTask() {
long now = System.currentTimeMillis() / 1000;
System.out.println(
"Fixed rate task with one second initial delay - " + now);
}
定时任务 cron
也可以通过设置cron表达式来指定定时任务的执行周期。
@Scheduled(cron = "0 15 10 15 * ?")
public void scheduleTaskUsingCronExpression() {
long now = System.currentTimeMillis() / 1000;
System.out.println(
"schedule tasks using cron jobs - " + now);
}
使用服务器的LocalTimeZone,同样也可以执行timezone
@Scheduled(cron = "0 15 10 15 * ?", zone = "Europe/Paris")
多线程
在单线程下,如果同时定义多个@Scheduled,当其中一个阻塞时,所有的定时任务都会被阻塞,
所以定义线程池非常有用。
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
threadPoolTaskScheduler.setPoolSize(5);
threadPoolTaskScheduler.setThreadNamePrefix("ThreadPoolTaskScheduler");
return threadPoolTaskScheduler;
}
如果使用springboot,配置将变得非常简单
spring.task.scheduling.pool.size=5
结论
spring提供的@Scheduled对于简单的定时任务来说使用很方便。同时值得注意的是,我们可以使用分布式作业调度器(如Quartz)来处理更复杂的调度场景。