今天在公司做事突然发现定时器没跑,原来自己少做了东西。。。
记录一下自己学习过的几种定时器,我就用springboot示范一下
1.@Scheduled
package com.example.test;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
@EnableScheduling
public class Test {
// 每10秒执行一次
@Scheduled(cron = "0/10 * * * * ?")
public void executeFileDownLoadTask() {
System.out.println("每10秒执行一次");
}
}
2.quartz
Quartz任务调度的核心元素为:Scheduler——任务调度器、Trigger——触发器、Job——任务。其中trigger和job是任务调度的元数据,scheduler是实际执行调度的控制器。
Trigger是用于定义调度时间的元素,即按照什么时间规则去执行任务。Quartz中主要提供了四种类型的trigger:SimpleTrigger,CronTirgger,DateIntervalTrigger,和NthIncludedDayTrigger。这四种trigger可以满足企业应用中的绝大部分需求。
Job用于表示被调度的任务。主要有两种类型的job:无状态的(stateless)和有状态的(stateful)。对于同一个trigger来说,有状态的job不能被并行执行,只有上一次触发的任务被执行完之后,才能触发下一次执行。Job主要有两种属性:volatility和durability,其中volatility表示任务是否被持久化到数据库存储,而durability表示在没有trigger关联的时候任务是否被保留。两者都是在值为true的时候任务被持久化或保留。一个job可以被多个trigger关联,但是一个trigger只能关联一个job。
Scheduler由scheduler工厂创建:DirectSchedulerFactory或者StdSchedulerFactory。第二种工厂StdSchedulerFactory使用较多,因为DirectSchedulerFactory使用起来不够方便,需要作许多详细的手工编码设置。Scheduler主要有三种:RemoteMBeanScheduler,RemoteScheduler和StdScheduler。
首先我们要引入依赖,如果不写版本号,spring-boot-starter-parenth会为我们提供常用jar包版本,自己指定版本号也可以,会覆盖官方版本
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
我们先创建一个类,类中有两个方法,一个是重写的方法,一个是普通的方法
package com.example.test;
import org.quartz.JobExecutionContext;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
@Component(value = "test1")
public class Test extends QuartzJobBean {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) {
System.out.println("Test 当前时间为:" + LocalDateTime.now() + ", 屌丝" + name + "已经" + age + "岁了");
}
public void test() {
System.out.println("Test1 当前时间是:" + LocalDateTime.now());
}
}
然后我们创建定时器的配置类,@Configuration注明类是配置类,@Bean是将方法提交容器启动管理
package com.example.test;
import org.quartz.CronTrigger;
import org.quartz.JobDataMap;
import org.quartz.SimpleTrigger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.*;
@Configuration
public class QuratzConfig {
//Job 编辑任务
@Bean
JobDetailFactoryBean job() {
JobDetailFactoryBean bean = new JobDetailFactoryBean();
bean.setJobClass(Test.class);//类要继承QuartzJobBean
JobDataMap jobDataMap = new JobDataMap();
jobDataMap.put("name", "张三");//填充参数,字段名要对应,可不填
jobDataMap.put("age", "25");//填充参数,字段名要对应,可不填
bean.setJobDataMap(jobDataMap);
bean.setDurability(true);
return bean;
}
//Job 编辑任务
@Bean
MethodInvokingJobDetailFactoryBean job1() {
MethodInvokingJobDetailFactoryBean bean = new MethodInvokingJobDetailFactoryBean();
bean.setTargetBeanName("test1");//类的bean名称
bean.setTargetMethod("test");//不能使用重写的方法
return bean;
}
//Trigger 创建定时器
@Bean
SimpleTriggerFactoryBean simpleTriggerFactoryBean() {
SimpleTriggerFactoryBean bean = new SimpleTriggerFactoryBean();
bean.setJobDetail(job().getObject());//可以对应不同的Job,一个job可以被多个trigger关联,但是一个trigger只能关联一个job
bean.setRepeatCount(5);//设置循环次数,实际运行六次
bean.setStartDelay(2000);//设置任务启动延迟时间,就是设置多久后开始第一次运行方法
bean.setRepeatInterval(5000);//设置任务的时间间隔
return bean;
}
//Trigger 创建定时器
@Bean
CronTriggerFactoryBean cronTriggerFactoryBean() {
CronTriggerFactoryBean bean = new CronTriggerFactoryBean();
bean.setJobDetail(job1().getObject());//可以对应不同的Job,一个job可以被多个trigger关联,但是一个trigger只能关联一个job
bean.setCronExpression("* * * * * ?");//corn表达式,每5秒执行一次
return bean;
}
//Scheduler 加载定时器
@Bean
SchedulerFactoryBean schedulerFactoryBean() {
SchedulerFactoryBean bean = new SchedulerFactoryBean();
SimpleTrigger simpleTrigger = simpleTriggerFactoryBean().getObject();
CronTrigger cronTrigger = cronTriggerFactoryBean().getObject();
bean.setTriggers(simpleTrigger, cronTrigger);
return bean;
}
}
3.Timer
使用Timer的schedule,schedule有3个参数:
schedule(TimerTask task, long delay, long period)
第一个为定时任务,根据业务需要重写TimerTask的run方法即可;
第二个为延时启动,就是设置多久后开始第一次运行方法,单位毫秒;
第三个位多久运行一次,单位毫秒;
首先我们先创建一个类,继承TimerTask,重写run方法
package com.example.test;
import java.time.LocalDateTime;
import java.util.TimerTask;
public class Test extends TimerTask {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Test(String name, Integer age) {
this.name = name;
this.age = age;
}
@Override
public void run() {
System.out.println("当前时间:" + LocalDateTime.now() + ", 屌丝" + name + "已经" + age + "岁了");
}
}
然后我们创建定时器的配置类,@Configuration注明类是配置类,@Bean是将方法提交容器启动管理
package com.example.test;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Timer;
@Configuration
public class MyTimer {
@Bean
public void ceshi() {
Timer timer = new Timer();
Test test = new Test("张三", 25);
timer.schedule(test, 2000L, 1000L);
}
}
网上还有一种是通过线程实现的,主要是依靠线程休眠处理,这里我就不说了