Spring提供了@Scheduled注解用于定时任务。
一、@Scheduled的基本使用
启用调度支持:@EnableScheduling
可以将@Scheduled注释与触发器元数据一起添加到方法中。例如,以下方法每隔5秒调用一次,并具有固定的延迟,这意味着周期是从前面每次调用的完成时间开始计算的
@Scheduled(fixedDelay=5000)
public void doSomething() {
// something that should execute periodically
}
如果需要固定速率执行,可以更改批注中指定的属性名。以下方法每5秒调用一次(在每次调用的连续开始时间之间计算)
@Scheduled(fixedRate=5000)
public void doSomething() {
// something that should execute periodically
}
对于固定延迟和固定速率任务,可以通过指示在首次执行方法之前要等待的毫秒数来指定初始延迟
@Scheduled(initialDelay=1000, fixedRate=5000)
public void doSomething() {
// something that should execute periodically
}
如果简单的周期性调度不够表达,可以提供cron表达式。例如,以http://www.cppcns.com下命令仅在工作日执行:
@Scheduled(cron="*/5 * * * * MON-FRI")
public void doSomething() www.cppcns.com{
// something that should execute on weekdays only
}
实现SchedulingConfigurer接口,重写configureTasks方法:
@Schedule注解的一个缺点就是其定时时间不能动态更改,它适用于具有固定任务周期的任务,若要修改任务执行周期,只能走“停服务→修改任务执行周期→重启服务”这条路。而基于 SchedulingConfigurer 接口方式可以做到。SchedulingConfigurer 接口可以实现在@Configuration等注解类上。
ScheduledTaskRegistrar类包括以下几个重要方法:
void addTriggerTask(Runnable task, Trigger trigger)
void addTriggerTask(TriggerTask task)
void addCronTask(Runnable task, String expression)
void addCronTask(CronTask task)
void addFixedRateTask(Runnable task, long interval)
void addFixedRateTask(IntervalTask task)
void addFixedDel
具体实现参考如下:
@Component
public class TestTask implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.addTriggerTask(new Runnable() {
@Override
public void run() {
// 定时任务要执行的内容
System.out.println("【开始执行定时任务。。。】");
}
}, new Trigger() {
数据库中
CronTrigger trigger = new CronTrigger(cron);
Date nextExecDate = trigger.nextExecutionTime(triggerContext);
return nextExecDate;
}
});
}
}
提示:如果在数据库修改时格式出现错误,则定时任务会停止,即使重新修改正确;此时只能重新启动项目才能恢复。
二、使用@Scheduled注意事项
spring的注解@Scheduled 需要写在实现方法上;
定时器的任务方法不能有返回值(如果有返回值,spring初始化的时候会告诉你有个错误、需要设定一个proxytargetclass的某个值为true),不能指向任何的参数;
如果该方法需要与应用程序上下文的其他对象进行交互,通常是通过依赖注入来实现;
实现类上要有组件的注解@Component。
三、使用@Scheduled常见问题
单线程任务丢失,转为异步线程池
默认的 ConcurrentTaskScheduler 计划执行器采用Executors.newSingleThreadScheduledExecutor() 实现单线程的执行器。因此,对同一个调度任务的执行总是同一个线程。如果任务的执行时间超过该任务的下一次执行时间,则会出现任务丢失,跳过该段时间的任务。上述问题有以下解决办法:
采用异步的方式执行调度任务,配置 Spring 的 @EnableAsync,在执行定时任务的方法上标注 @Async配置任务执行池,线程池大小 n 的数量为 单个任务执行所需时
//每30秒执行一次
@Async("taskExecutor")
@Scheduled(fixedRate = 1000 * 3)
public void reportCurrentTime(){
System.out.println ("线程" + Thread.currentThread().getName() + "开始执行定时任务===&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&7&&&====》"
+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
long start = System.currentTimeMillis();
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。
本文标题: Spring内置定时任务调度@Scheduled使用详解
本文地址: http://www.cppcns.com/ruanjian/java/367902.html