一、Java实现定时任务的方式
一、线程等待(不建议使用,任务复杂时存在内存泄露风险)
Thread myThread = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
System.out.println("TestThreadWait is called!");
try {
// 使用线程休眠来实现周期执行
Thread.sleep(1000 * 3);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
myThread.start();
二、Timer
import java.util.Timer;
import java.util.TimerTask;
public class Main {
public static void main(String[] args) {
/*Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("执行定时任务");
}
},1000,1000);*/
TimerTask task = new TimerTask() {
@Override
public void run() {
System.out.println("TimerTask is called!");
}
};
Timer timer = new Timer();
/*
* schedule 和 scheduleAtFixedRate 区别:
* 可将schedule理解为scheduleAtFixedDelay,
* 两者主要区别在于delay和rate
* 1、schedule,如果第一次执行被延时(delay),
* 随后的任务执行时间将以上一次任务实际执行完成的时间为准
* 2、scheduleAtFixedRate,如果第一次执行被延时(delay),
* 随后的任务执行时间将以上一次任务开始执行的时间为准(需考虑同步)
*
* 参数:1、任务体 2、延时时间(可以指定执行日期)3、任务执行间隔时间
*/
// timer.schedule(task, 0, 1000 * 3);
timer.scheduleAtFixedRate(task, 0, 1000 * 3);
}
}
三、ScheduledExecutorService
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) {
Runnable runnable = new Runnable() {
public void run() {
System.out.println("ScheduledExecutorService Task is called!");
}
};
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
// 参数:1、任务体 2、首次执行的延时时间
// 3、任务执行间隔 4、间隔时间单位
service.scheduleAtFixedRate(runnable, 0, 3, TimeUnit.SECONDS);
}
}
四、@Scheduled
1、配置
在spring boot的启动类上加@EnableScheduling注解,允许支持@Scheduled:
@SpringBootApplication
@EnableScheduling
public class Quartz01Application {
public static void main(String[] args) {
SpringApplication.run(Quartz01Application.class, args);
}
}
2、任务类
@Component
public class ScheduleTask {
// 每隔5秒执行一次
@Scheduled(cron = "0/5 * * * * ?")
public void printSay() {
System.out.println("每隔5秒执行一次:" + new Date());
}
}
二、Quartz介绍
quartz是一种基于java实现的任务调度框架,可以定时自动的执行你想要执行的任何任务。
quartz官网:Quartz Enterprise Job Scheduler
二、Quartz的组成
任务Job(你要做什么事? 将要执行的操作)
job就是你想要实现的任务类,每一个job必须实现org.quartz.job接口。
触发器Trigger(你什么时候去做? cron表达式)
Trigger为你执行任务的触发器,比如你想每天定时3点发送一份统计邮件,Trigger将会设置3点进行执行该任务。
调度器Scheduler(你什么时候需要做什么事?)
Scheduler为任务的调度器,它会将任务job及触发器Trigger整合起来,负责基于Trigger设定的时间来执行Job。
三、使用java实现一个简单的Quartz例子
1、新建一个maven项目,并引入Quartz依赖
<dependencies>
<!--核心包-->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version>
</dependency>
<!--工具-->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.3.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.7</version>
<scope>compile</scope>
</dependency>
</dependencies>
2、编写一个Job类,用来编写定时任务要做什么
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class HelloJob implements Job {
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
//输出当前时间
Date date=new Date();
SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString=dateFormat.format(date);
//工作内容
System.out.println("执行定时任务,时间是:"+dateString);
}
}
3、编写触发器和调度器
import com.changan.test.service.HelloJob;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
public class HelloSchedulerDemo {
public static void main(String[] args) throws Exception{
//1、调度器(Schedular),从工厂中获取调度实例(默认:实例化new StdSchedulerFactory();)
Scheduler scheduler= StdSchedulerFactory.getDefaultScheduler();
//2、任务实例(JobDetail)
JobDetail jobDetail= JobBuilder.newJob(HelloJob.class) //加载任务类,与HelloJob完成绑定,要求HelloJob实现Job接口
.withIdentity("job1","group1") //参数1:任务的名称(唯一实例);参数2:任务组的名称
.build();
//3、触发器(Trigger)
Trigger trigger= TriggerBuilder.newTrigger()
.withIdentity("trigger1","group1") //参数1:触发器的名称(唯一实例);参数2:触发器组的名称
.startNow() //马上启动触发器
.withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(5)) //每5秒执行一次
.build();
//让调度器关联任务和触发器,保证按照触发器定义的条件执行任务
scheduler.scheduleJob(jobDetail,trigger);
//启动
scheduler.start();
}
}
4.启动项目
四、使用Springboot整合Quartz定时任务框架
1.pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
2、 job类
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.util.Date;
public class QuartzDemo implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("Execute..."+new Date());
}
}
3、配置类,配置触发器与任务调度器
import com.changan.service.QuartzDemo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.scheduling.quartz.SimpleTriggerFactoryBean;
/**
* Quartz配置类
*/
@Configuration
public class QuartzConfig {
/**
* 1、创建Job对象
*/
@Bean
public JobDetailFactoryBean jobDetailFactoryBean(){
JobDetailFactoryBean factoryBean=new JobDetailFactoryBean();
//关联我们自己的Job类
factoryBean.setJobClass(QuartzDemo.class);
return factoryBean;
}
/**
* 2、创建Trigger对象
*/
@Bean
public SimpleTriggerFactoryBean simpleTriggerFactoryBean(JobDetailFactoryBean jobDetailFactoryBean){
SimpleTriggerFactoryBean factoryBean=new SimpleTriggerFactoryBean();
//关联JobDetail对象
factoryBean.setJobDetail(jobDetailFactoryBean.getObject());
//该参数表示一个执行的毫秒数
factoryBean.setRepeatInterval(2000); //每隔2秒执行一次
//重复次数
factoryBean.setRepeatCount(5);
return factoryBean;
}
/**
* 3、创建Scheduler
*/
@Bean
public SchedulerFactoryBean schedulerFactoryBean(SimpleTriggerFactoryBean simpleTriggerFactoryBean){
SchedulerFactoryBean factoryBean=new SchedulerFactoryBean();
//关联trigger
factoryBean.setTriggers(simpleTriggerFactoryBean.getObject());
return factoryBean;
}
}
4、启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class Quartz01Application {
public static void main(String[] args) {
SpringApplication.run(Quartz01Application.class, args);
}
}
五、使用Springboot+mybatis整合Quartz定时任务框架实现定时向数据库插入一条数据
QuartzDemo
import com.changan.entity.User;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Date;
public class QuartzDemo implements Job {
@Autowired
private UserService userService;
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
User user = new User();
user.setEmail("123123");
user.setAge(12);
user.setName("456");
userService.save(user);
}
}
因此我们需要手动的把QuartzDemoJob类注入到SpringIOC容器中。
编写一个类MyAdaptableJobFactory继承AdaptableJobFactory,覆盖createJobInstance()方法。
MyadaptableJobFactory
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.scheduling.quartz.AdaptableJobFactory;
import org.springframework.stereotype.Component;
@Component("myadaptableJobFactory") //将该类实例化,使得可以直接用
public class MyadaptableJobFactory extends AdaptableJobFactory {
//AutowireCapableBeanFactory可以将一个对象添加到Spring IOC容器中,并且完成该对象注入
@Autowired
private AutowireCapableBeanFactory autowireCapableBeanFactory;
//该方法将实例化的任务对象手动的添加到SpringIOC容器中并且完成对象的注入
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
Object object = super.createJobInstance(bundle);
//将object对象添加到Spring IOC容器中并完成注入
this.autowireCapableBeanFactory.autowireBean(object);
return object;
}
}
QuartzConfig
import com.changan.service.QuartzDemo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.scheduling.quartz.SimpleTriggerFactoryBean;
/**
* Quartz配置类
*/
@Configuration
public class QuartzConfig {
/**
* 1、创建Job对象
*/
@Bean
public JobDetailFactoryBean jobDetailFactoryBean(){
JobDetailFactoryBean factoryBean=new JobDetailFactoryBean();
//关联我们自己的Job类
factoryBean.setJobClass(QuartzDemo.class);
return factoryBean;
}
/**
* 2、创建Trigger对象
*/
@Bean
public SimpleTriggerFactoryBean simpleTriggerFactoryBean(JobDetailFactoryBean jobDetailFactoryBean){
SimpleTriggerFactoryBean factoryBean=new SimpleTriggerFactoryBean();
//关联JobDetail对象
factoryBean.setJobDetail(jobDetailFactoryBean.getObject());
//该参数表示一个执行的毫秒数
factoryBean.setRepeatInterval(2000); //每隔2秒执行一次
//重复次数
factoryBean.setRepeatCount(5);
return factoryBean;
}
/**
* 3、创建Scheduler
*/
@Bean
public SchedulerFactoryBean schedulerFactoryBean(SimpleTriggerFactoryBean simpleTriggerFactoryBean, MyadaptableJobFactory myadaptableJobFactory){
SchedulerFactoryBean factoryBean=new SchedulerFactoryBean();
//关联trigger
factoryBean.setTriggers(simpleTriggerFactoryBean.getObject());
factoryBean.setJobFactory(myadaptableJobFactory);
return factoryBean;
}
}
CronExpression表达式