写在前面
定时任务是项目开发中最常见的功能之一,如定时统计订单数、定时进行数据库备份、定时发送邮件以及周期性调度等。简单的定时任务可以直接通过 Spring 的 @Scheduled 注解实现,复杂的定时任务则可以通过集成 Quartz 来实现。
(1)@Scheduled只能针对本机的任务进行调度,当应用为了增加发负载量,都是使用多机部署时,就会出现问题:在每一台机器上都会同时执行定时调度任务,产生很多重复/垃圾数据。所以在使用@Scheduled进行任务调度时,一定要配合REDIS的分布式锁,让定时调度任务只在一台机器上执行。
(2)所有的定时任务都是由同一个线程池的同一个线程来完成的,如果有多个定时任务,其中一个任务执行时间过长,则有可能会导致其他后续任务被阻塞直到该任务执行完成。如何解决呢?
如何使用@Scheduled?
1. 开启定时任务
在项目启动类上添加 @EnableScheduling 注解开启定时任务。
2. 设置定时任务
@Component
public class MySchedule {
// fixedDelay, 表示上次调用结束后与下次调用之间的固定时间,单位是毫秒
// 表示距离上次调用后1秒再执行
@Scheduled(fixedDelay = 1000)
public void fixedDelay() {
System.out.println("fixedDelay:" + new Date());
}
// fixedRate, 表示多久执行一次,单位是毫秒,与cron的/通配符用法相似
// 表示每2秒执行一次
@Scheduled(fixedRate = 2000)
public void fixedRate() {
System.out.println("fixedRate:" + new Date());
}
// initialDelay, 表示第一次延迟多少毫秒执行,单位是毫秒
// 表示每2秒执行一次, 第一次执行时, 延迟2秒执行
@Scheduled(initialDelay = 1000, fixedRate = 2000)
public void initialDelay() {
System.out.println("initialDelay:" + new Date());
}
// 使用cron 表达式(每分钟执行一次)
@Scheduled(cron = "0 * * * * ?")
public void cron() {
System.out.println("cron:" + new Date());
}
}
注意事项
(1)SPRING的@Scheduled注解需要标注在实现方法上;
(2)被@Scheduled标注的方法不能有返回值;
(3)如果被@Scheduled标注的方法需要与应用程序上下文的其他对象进行交互,通常是通过依赖注入的方式来实现;
(4)被@Scheduled标注的方法的类上要有组件的注解@Component;(当然也可以使用 @Controller 和 @Service 等其他与 @Component 作用相同的注解)
(5)所有的定时务在同一个线程中。