Quartz定时任务

发布时间 2023-03-27 22:04:24作者: 秋夜雨巷

Java实现定时任务的方式

Thread线程等待(不建议使用,任务复杂时存在内存泄露风险)

/* 线程等待(不建议使用,任务复杂时存在内存泄露风险) */
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();

image

Timer

//声明做什么任务
TimerTask task = new TimerTask() {
    @Override
    public void run() {
        System.out.println("TimerTask is called!");
    }
};

//声明调度者
Timer timer = new Timer();

/*
 *  timer.schedule 和 timer.scheduleAtFixedRate 区别:
 *  1、schedule,如果第一次执行被延时(delay),
 *      随后的任务执行时间将以上一次任务执行完成的时间为准
 *  2、scheduleAtFixedRate,如果第一次执行被延时(delay),
 *      随后的任务执行时间将以上一次任务执行开始的时间为准(需考虑同步)
 */
// timer.schedule(任务体, 延时时间, 任务执行间隔时间);
//调度者指定什么时候做什么任务
timer.scheduleAtFixedRate(task, 1000 * 1, 1000 * 3);

image

ScheduledExecutorService

// 1.声明做什么任务
Runnable runnable = new Runnable() {
    public void run() {
        System.out.println("ScheduledExecutorService Task is called!");
    }
};
// 2.声明调度者
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
// 3.调度者什么时候做什么任务
// 参数:1、任务体 2、首次执行的延时时间 3、任务执行间隔 4、间隔时间单位
scheduledExecutorService.scheduleAtFixedRate(runnable, 0, 3, TimeUnit.SECONDS);

image

Spring注解@Scheduled

1、配置
在spring boot的启动类上加@EnableScheduling注解,允许支持@Scheduled:

@SpringBootApplication
@EnableScheduling         //开启定时任务
public class SpringbootApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringbootApplication.class, args);
    }
}

2、任务类

@Component
public class ScheduleTask {
    // 每隔5秒执行一次
    @Scheduled(cron = "0/5 * * * * ?")
    public void printSay() {
        System.out.println("每隔5秒执行一次:" + new Date());
    }
}

@Scheduled详细

Quartz

quartz是一种基于java实现的任务调度框架,可以定时自动的执行你想要执行的任何任务。
quartz官网

Quartz的组成

1.任务Job(你要做什么事? 将要执行的操作)
job就是你想要实现的任务类,每一个job必须实现org.quartz.job接口。

2.触发器Trigger(你什么时候去做? cron表达式)
Trigger为你执行任务的触发器,比如你想每天定时3点发送一份统计邮件,Trigger将会设置3点进行执行该任务。

3.调度器Scheduler(你什么时候需要做什么事?)
Scheduler为任务的调度器,它会将任务job及触发器Trigger整合起来,负责基于Trigger设定的时间来执行Job。

pom.xml

<!--quartz核心包-->
<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.3.2</version>
</dependency>
<!--quartz工具-->
<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>

任务类(job)

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
//Job类,用来编写定时任务要做什么
public class QuartzJob implements Job {
    @Override
    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);
    }
}

调度器和触发器

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

public class QuartzSchedule {
    public static void main(String[] args) throws SchedulerException {
        //1、调度器(Schedular),从工厂中获取调度实例(默认:实例化new StdSchedulerFactory();)
        Scheduler scheduler= StdSchedulerFactory.getDefaultScheduler();
        //2、任务实例(JobDetail)
        JobDetail jobDetail= JobBuilder.newJob(QuartzJob.class) //加载任务类,与QuartzJob完成绑定,要求QuartzJob实现Job接口
                .withIdentity("jobid","groupname")  //参数1:任务的名称(唯一实例);参数2:任务组的名称
                .build();
        //3、触发器(Trigger)
        Trigger trigger= TriggerBuilder.newTrigger()
                .withIdentity("triggerid","groupname") //参数1:触发器的名称(唯一实例);参数2:触发器组的名称
                .startNow() //马上启动触发器
                .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(5)) //每5秒执行一次
                .build();
        //4、让调度器关联任务和触发器,保证按照触发器定义的条件执行任务
        scheduler.scheduleJob(jobDetail,trigger);
        //启动
        scheduler.start();
    }
}

image

SpringBoot整合Quartz

pom.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

Job类

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.util.Date;
public class QuartzSPDemo implements Job {
        @Override
        public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
            System.out.println("Execute..."+new Date());
    }
}

任务调度器与触发器

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(QuartzSPDemo.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;
    }
}

因为是Spring整合Quartz,所以只需要给出Scheduler、Job、Trigger即可,spring会自动把任务和触发器关联起来。
Springboot启动类加上@EnableScheduling注解,然后直接启动启动类即可。

但是如果要在任务中操作数据库,job任务需要从ioc容器中获取service实例。
参考:https://blog.csdn.net/m0_60286388/article/details/127402055