一、Spring Schedule
直接使用注解方式。
引入依赖:
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<version>2.1.2.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.1.2.RELEASE</version>
</dependency>
1、简单的固定间隔时间任务
@Component
public class ScheduleTest {
public final static long TIME = 1 * 1000;
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 每2S执行一次任务
@Scheduled(fixedRate = TIME * 2)
public void testJob01() throws InterruptedException {
System.out.println("执行任务:" + dateFormat.format(new Date()));
}
}
启动类加上@EnableScheduling注解:
@SpringBootApplication
@EnableScheduling
public class APP {
public static void main(String[] args) {
SpringApplication.run(APP.class, args);
}
}
2、自定义的Corn表达式任务
Cron 表达式定义时间规则,Cron 表达式由 6 或 7 个空格分隔的时间字段组成。
Cron 表达式中的特殊字符:
*:可用于所有字段,表示对应时间域的每一个时刻。例如:* 在分钟字段时,表示 每分钟
?:只能用在日期和星期字段中,表示一个毫无意义的值,相当于占位符
-:表示一个范围。例如:在小时字段中使用 10-12,表示从 10 点到 12 点。即 10,11, 12
,:表示一个列表值。例如:在星期字段中使用 MON,WED,FRI,表示星期一,星期三,星期五
/:x/y 表示一个等步长序列,x 为起始值,y 为增量步长。例如:在分钟字段中使用 0/15,则表示为 0,15,30 和 45 秒;而 5/15 在分钟字段表示 5,20,35,50 。*/y 等同于 0/y
L:该字符只在日期和星期字段中使用,代表 Last。
L 用在日期字段中,代表这个月的最后一天
L 用在星期字段中,代表星期六
若 L 出现在星期字段里,且前面有一个数值 X,则表示 这个月的最后星期 X,例如 6L 表示该月的最后一个星期五
W:该字符只能出现在日期字段里,是对前导日期的修饰,表示离该日期最近的工作日。例如:15W 表示离该月 15 号最近的工作日:若 15 号是星期六,则匹配 14 号;若 15 号是星期日,则匹配 16 号;若 15 号是星期二,则匹配 15 号。
注意1:关联的匹配日期不能跨月。例如用户指定 1W,若 1 号是星期六,则匹配 3 号。
注意2:W 字符串只能指定单一日期,而不能指定日期范围。
LW:在日期字段可以组合使用 LW,意为当月的最后一个工作日
#:只能在星期字段中使用,表示当月某个工作日。例如:6#3 表示当月的第三个星期五(6表示星期五,#3表示当月的第三个),4#5 表示当月的第五个星期三,若没有第五个星期三,则忽略不触发
C:该字符只在日期和星期字段中使用,代表 Calendar。意为计划所关联的日期,如果日期没有被关联,则相当于日历中所有日期。例如:5C 在日期字段中就相当于 5 日以后的第一天。1C 在星期字段中相当于星期日后的第一天。
例如:
0 0 12 * * ?:每天中午12点触发
0 15 10 ? * *:每天上午10:15触发
0 15 10 * ? *: 每天上午10:15触发
0 15 10 * * ? 2005: 2005年的每天上午10:15触发
0 * 14 * * ?:在每天下午2点到下午2:59期间的每1分钟触发
0 0/5 14 * * ?:在每天下午2点到下午2:55期间的每5分钟触发
0 0/5 14, 18 * * ?:在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟,触发
0 0-5 14 * * ?:在每天下午2点到下午2:05期间的每1分钟触发
0 10,20 14 ? 3 WED:每年三月的星期三的下午2:10和2:20触发
0 15 10 ? * MON-FRI:周一至周五的上午10:15 触发
0 15 10 15 * ?:每月15日上午10:15 触发
0 15 10 L * ?:每月最后一日的上午10:15 触发
0 15 10 ? * 6L:每月的最后一个星期五上午10:15 触发
0 15 12 ? * 6L 2018-2019:2018年至2019年的每月的最后一个星期五上午12:15触发
0 15 10 ? * 6#3:每月的第三个星期五上午10:15触发
@Component
public class ScheduleTest {
public final static long TIME = 1 * 1000;
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// Cron公式, 每三秒执行一次任务
@Scheduled(cron = "0/3 * * * * ?")
public void testJob02() throws InterruptedException {
System.out.println("执行任务:" + dateFormat.format(new Date()));
}
}
二、Quartz
Quartz是一个任务调度框架,是一个很轻量级的java库,几乎包含了所有定时的功能。美团正在大量使用。
Quartz 对任务调度的领域问题进行了高度抽象,提出了调度器、任务和触发器 3 个核心概念。
Job:接口。开发者通过实现该接口定义需要执行的任务。
JobDetail:Quartz 在每次执行 Job 时,都重新创建一个 Job 实例,所以它不是直接接受一个 Job 的实例,而是接受一个 Job 实现类,以便运行时通过反射机制实例化 Job。因此需要一个类来描述 Job 的实现类及其他相关的静态信息,如 Job 名称、描述、关联
的监听器等,JobDetail 承担了这一角色。
Trigger:描述触发 Job 执行的时间触发规则。主要有 SimpleTrigger、CronTrigger 两个实现类。
SimpleTrigger:当仅需要触发一次或者以固定间隔周期执行时。
CronTrigger:可以通过 Cron 表达式定义出各种复杂的调度方案。
Calendar:一些日历特定时间点的集合(可以简单的理解为 java.util.Calendar 的集合:java.util.Calendar )。一个 Trigger 可以和多个 Calendar 关联,以便包含或排除某些时间点。
Scheduler:一个 Quartz 的独立运行容器,Trigger 和 JobDetail 可以注册到 Scheduler 中,两者在 Scheduler 中拥有各自的组及名称。组及名称是 Scheduler 查找容器中某一对象的依据,Trigger 和 JobDetail 的组及名称的组合都必须唯一(但 Scheduler
和 Trigger 的组合名称可以相同,因为他们是不同的类型,处于不同的容器中)。Scheduler 可以将 Trigger 绑定到某一个 JobDetails 中,这样当 Trigger 被触发时,对应的 Job 就被执行。一个 Job 可以对应多个 Trigger,但一个 Trigger 只能对应一个 Job。
引入依赖:
“Springboot 2.0.x” 版本:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
- 创建任务类TestQuartz,该类继承了QuartzJobBean
public class TestQuartz extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("执行任务: "+new Date());
}
}
- 创建配置类
QuartzConfig
@Configuration
public class QuartzConfig {
@Bean
public JobDetail teatQuartzDetail(){
return JobBuilder.newJob(TestQuartz.class).withIdentity("testQuartz").storeDurably().build();
}
@Bean
public Trigger testQuartzTrigger(){
SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(10) //设置时间周期 秒
.repeatForever();
return TriggerBuilder.newTrigger().forJob(teatQuartzDetail())
.withIdentity("testQuartz")
.withSchedule(scheduleBuilder)
.build();
}
}
启动项目即可。