Quartz 基本使用

一、Quartz的核心概念

  Quartz [kwɔːts] 是OpenSymphony开源组织在Job scheduling领域又一个开源项目,完全由Java开发,可以用来执行定时任务,类似于java.util.Timer。但是相较于Timer, Quartz增加了很多功能:

   1.持久性作业 - 就是保持调度定时的状态;
   2.作业管理 - 对调度作业进行有效的管理;

  Quartz是一个强大任务调度框架,可以用来干嘛?如一个OA系统需要在每周五9点自动生成数据报表,或者想每月10号自动还款,又或者每周给暗恋的女生定时发送邮件等等。下面介绍Quartz的三个核心概念(job,Trigger,Scheduler)。

  1,任务job

    job就是你想实现的任务类,每一个job必须实现org.quartz.job接口,且只需实现接口定义的execute()方法。

    Job:工作任务调度的接口,任务类需要实现该接口,该接口中定义execute方法,类似jdk提供的TimeTask类的run方法,在里面编写任务执行的业务逻辑。

    Job:实例在Quartz中的生命周期,每次调度器执行job时它在调用execute方法前,会创建一个新的job实例,当调用完成后,关联的job对象实例会被是释放,释放的实例会被垃圾回收机制回收。

  2,触发器Trigger

    Trigger 为你执行任务的触发器,比如你想每天定时1点发送邮件,Trigger将会设置1点执行该任务。

    Trigger主要包含两种:SimpleTrigger和CronTriggerr。

  3,调度器Scheduler

    Scheduler是任务的调度器,会将任务job和触发器TRigger结合,负责基于Trigger设定的时间执行job。

二、Quartz的几个常用API

  Scheduler :用于与调度程序交互的主程序接口。

  Job :预先定义的希望在未来时间被调度程序执行的任务类,自定义。

  JobDetall :使用JobDetail来定义定时任务的实例,JobDetail实例是通过JobBuilder类创建。

  JobDataMap :可包含数据对象,在job实例执行的是好,可使用包含的数据;JobDataMap是java Map接口的实现,增加了一些存取基本类型方法。

  Trgger触发器 :Trigger对象是用于触发执行Job的,当调度一个Job时,我们实例一个触发器然后调整它的属性来满足Job执行的条件,表明任务在什么时候执行。定义了一个已经被安排的任务将在什么时候执行的时间条件,比如每秒执行一次。

  JobBuilder :用于声明一个任务实例,也可以定义关于该任务的详情比如:任务名,组名等,这个声明的实例将作为一个实例执行的任务。

  TriggerBuilder :触发器创建器,用于创建触发器trigger实例。

  JobListener,TriggerListener,SchedulerListener监听器,用于对组件的监听。

三、Quartz的使用

  创建项目并加入依赖

<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.3.1</version>
</dependency>

  新建一个能够打印任意内容的Job:

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;

public class PrintWordsJob implements Job {

    @Override
    public void execute(JobExecutionContext jobExecutionContext) {
        String printTime = new SimpleDateFormat("yy-MM-dd HH-mm-ss").format(new Date());
        System.out.println("PrintWordsJob start at:" + printTime + ", prints: Hello Job-" + new Random().nextInt(100));

    }
}

  创建Schedule,执行任务:

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import java.util.concurrent.TimeUnit;

public class MyScheduler {

    public static void main(String[] args) throws SchedulerException, InterruptedException {

        // 1、创建JobDetail实例,并与PrintWordsJob类绑定(Job执行内容)
        JobDetail jobDetail = JobBuilder.newJob(PrintWordsJob.class)
                                        .withIdentity("job1", "group1").build();
        // 2、构建Trigger实例,每隔1s执行一次
        Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "triggerGroup1")
                .startNow()//立即生效
                .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                .withIntervalInSeconds(1)//每隔1s执行一次
                .repeatForever()).build();//一直执行

        //3、创建调度器Scheduler并执行
        Scheduler scheduler = new StdSchedulerFactory().getScheduler();
        scheduler.scheduleJob(jobDetail, trigger);
        System.out.println("--------scheduler start ! ------------");
        scheduler.start();

        //睡眠
        TimeUnit.MINUTES.sleep(1);
        scheduler.shutdown();
        System.out.println("--------scheduler shutdown ! ------------");

    }
}

  运行程序,可以看到程序每隔1s会打印出内容,且在一分钟后结束。

四、Quartz核心详解

  1.Job和JobDetail

    Job是Quartz中的一个接口,接口下只有execute方法,在这个方法中编写业务逻辑。

  JobDetail用来绑定Job,为Job实例提供许多属性:

  name group jobClass jobDataMap

  JobDetail绑定指定的Job,每次Scheduler调度执行一个Job的时候,首先会拿到对应的Job,然后创建该Job实例,再去执行Job中的execute()的内容,任务执行结束后,关联的Job对象实例会被释放,且会被JVM GC清除。

  为什么设计成JobDetail + Job,不直接使用Job

  JobDetail定义的是任务数据,而真正的执行逻辑是在Job中。 这是因为任务是有可能并发执行,如果Scheduler直接使用Job,就会存在对同一个Job实例并发访问的问题。而JobDetail & Job 方式,Sheduler每次执行,都会根据JobDetail创建一个新的Job实例,这样就可以规避并发访问的问题。

  2.Trigger、SimpleTrigger、CronTrigger

  Trigger

    Trigger是Quartz的触发器,会去通知Scheduler何时去执行对应Job。

    new Trigger().startAt():表示触发器首次被触发的时间;

    new Trigger().endAt():表示触发器结束触发的时间;

  SimpleTrigger

    SimpleTrigger可以实现在一个指定时间段内执行一次作业任务或一个时间段内多次执行作业任务。

  下面的程序就实现了程序运行5s后开始执行Job,执行Job 5s后结束执行:

Date startDate = new Date();
startDate.setTime(startDate.getTime() + 5000);

Date endDate = new Date();
endDate.setTime(startDate.getTime() + 5000);

Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "triggerGroup1")
        .usingJobData("trigger1", "这是jobDetail1的trigger")
        .startNow()//立即生效
        .startAt(startDate)
        .endAt(endDate)
        .withSchedule(SimpleScheduleBuilder.simpleSchedule()
        .withIntervalInSeconds(1)//每隔1s执行一次
        .repeatForever()).build();//一直执行

CronTrigger

  CronTrigger功能非常强大,是基于日历的作业调度,而SimpleTrigger是精准指定间隔,所以相比SimpleTrigger,CroTrigger更加常用。CroTrigger是基于Cron表达式的,先了解下Cron表达式: 由7个子表达式组成字符串的,格式如下:

[] [] [小时] [] [] [] []

Cron表达式的语法比较复杂,

如:* 30 10 ? * 1/5 * 表示(从后往前看)

[指定年份] 的[ 周一到周五][指定月][不指定日][上午10时][30分][指定秒]

又如:00 00 00 ? * 10,11,12 1#5 2018

表示2018年10、11、12月的第一周的星期五这一天的0时0分0秒去执行任务。

在线生成corn表达式:http://cron.qqe2.com/

下面的代码就实现了每到整分时执行一次定时任务

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

public class MyScheduler2 {
    public static void main(String[] args) throws SchedulerException, InterruptedException {
        //1.创建JobDetail实例,并与PrintWordsJob类绑定(Job执行内容)
        JobDetail jobDetail=JobBuilder.newJob(PrintWordsJob.class)
                .usingJobData("jobDetail", "这个Job用来测试的")
                .withIdentity("job","group")
                .build();
        //2.触发器
        CronTrigger trigger=TriggerBuilder.newTrigger().withIdentity("trigger", "group").startNow()//立刻执行
                .usingJobData("trigger1", "这是jobDetail1的trigger")
                .withSchedule(CronScheduleBuilder.cronSchedule("0 * * * * ?"))//表示每次0秒时候执行。
                .build();
        //3.调度器
        Scheduler scheduler = new StdSchedulerFactory().getScheduler();
        scheduler.scheduleJob(jobDetail,trigger);
        System.out.println("--------scheduler start ! ------------");
        scheduler.start();
        System.out.println("--------scheduler shutdown ! ------------");

    }
}

五、JobListener

  创建MyJobListener实现JobListener接口

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobListener;

public class MyJobListener implements JobListener {


    public String getName() {
        return this.getClass().getSimpleName();
    }

    //Scheduler在jobDetail将要被执行时调用这个方法(执行前)
    public void jobToBeExecuted(JobExecutionContext context) {
        String jobName = context.getJobDetail().getKey().getName();
        System.out.println("我的job名1:" + jobName);
    }

    //Scheduler在jobDetail即将被执行,但又被TriggerListermer 否定时会调用该方法
    public void jobExecutionVetoed(JobExecutionContext context) {
        String jobName = context.getJobDetail().getKey().getName();
        System.out.println("我的job名2:" + jobName);
    }

    //Scheduler在jobDetail即将被执行之后调用这个方法。(执行后)
    public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
        String jobName = context.getJobDetail().getKey().getName();
        System.out.println("我的job名3:" + jobName);
    }
}

  在scheduler创建后加入监听即可生效

  scheduler.getListenerManager().addJobListener(new MyJobListener());

六、TriggerListener

  任务调度过程中,与触发器Trigger相关的事件包括:触发器触发,触发器未正常触发,触发器完成等。

import org.quartz.JobExecutionContext;
import org.quartz.Trigger;
import org.quartz.TriggerListener;

public class MyTriggerListener implements TriggerListener {
    //用于获取触发器的名称	
    public String getName() {//获取默认类名
        return this.getClass().getSimpleName();
    }

    //当与监听器相关联的trigger被触发,job上的execute()方法将被执行时,Scheduler就调用该方法
    public void triggerFired(Trigger trigger, JobExecutionContext context) {
        System.out.println("triggerFired");
    }
    //在Trigger触发后,job将要被执行时由Scheduler调用这个方法。
    //TriggerListener给一个选择去否决job的执行。如方法返回true,job此次将不会为trigger触发执行。false,放行。
    public boolean vetoJobExecution(Trigger trigger, JobExecutionContext context) {
        System.out.println("vetoJobExecution");
        return false;
    }
    //Scheduler 调用这个方法是在trigger错过时触发。
    public void triggerMisfired(Trigger trigger) {
        System.out.println("triggerMisfired");
    }
    //triggerComplete:trigger被触发并且完成了job的执行时,Scheduler调用这个方法。
    public void triggerComplete(Trigger trigger, JobExecutionContext context,
            Trigger.CompletedExecutionInstruction triggerInstructionCode) {
        System.out.println("triggerComplete");
    }
	
}

scheduler.getListenerManager().addTriggerListener(new MyTriggerListener());

七、SchedulerListener

  SchedulerListener会在scheduler的生命周期中关键事件发生时被调用,与Scheduler有关事件;增加或者删除一个 job/trigger,关闭scheduler等。

import org.quartz.*;

public class MySchedulerListener implements SchedulerListener {
	
	//用于部署JobDetail 的时候调用
	public void jobScheduled(Trigger trigger) {
		String name = trigger.getKey().getName();
		System.out.println("获取触发器名称:"+name);
	}
	//卸载JobDetail 的时候调用
	public void jobUnscheduled(TriggerKey triggerKey) {
		System.out.println(triggerKey.getName());
	}
	//当trigger来到再也不会触发的时候调用这个方法
	public void triggerFinalized(Trigger trigger) {
		String name = trigger.getKey().getName();
		System.out.println("获取触发器名称:"+name);
	}
	//当trigger 被暂停时候调用
	public void triggerPaused(TriggerKey triggerKey) {
		System.out.println("被暂停1");
	}
	//当trigger组  被暂停时候调用
	public void triggersPaused(String triggerGroup) {
		System.out.println("被暂停2");
	}
	///当trigger从  被暂停 到恢复 时候 调用
	public void triggerResumed(TriggerKey triggerKey) {
		System.out.println("恢复");
	}
	///当trigger组从  被暂停 到恢复 时候 调用
	public void triggersResumed(String triggerGroup) {
		System.out.println("恢复");
	}
	//添加工作任务调用
	public void jobAdded(JobDetail jobDetail) {
		System.out.println("添加工作任务");
		
	}
	//删除工作任务
	public void jobDeleted(JobKey jobKey) {
		System.out.println("删除工作任务");
		
	}
 
	public void jobPaused(JobKey jobKey) {
		// TODO Auto-generated method stub
		
	}
 
	public void jobsPaused(String jobGroup) {
		// TODO Auto-generated method stub
		
	}
 
	public void jobResumed(JobKey jobKey) {
		// TODO Auto-generated method stub
		
	}
 
	public void jobsResumed(String jobGroup) {
		// TODO Auto-generated method stub
		
	}
	//scheduler产生Error调用
	public void schedulerError(String msg, SchedulerException cause) {
		// TODO Auto-generated method stub
		
	}
	//scheduler被挂起时候调用
	public void schedulerInStandbyMode() {
		// TODO Auto-generated method stub
		
	}
	//scheduler开启的时候调用
	public void schedulerStarted() {
		System.out.println("scheduler kai qi ");
		
	}
	//scheduler 正在开启的时候调用 ing.....
	public void schedulerStarting() {
		System.out.println("scheduler 正在开启的时候调用 ing.....");
		
	}
	scheduler关闭 的时候调用
	public void schedulerShutdown() {
		System.out.println("scheduler关闭 的时候调用");
		
	}
	//scheduler 正在关闭的时候调用 ing.....
	public void schedulerShuttingdown() {
		System.out.println("//scheduler 正在关闭的时候调用 ing.....");
		
	}
	//scheduler 数据被清除了的时候调用
	public void schedulingDataCleared() {
		System.out.println("//scheduler 数据被清除了的时候调用");
		
	}
 
}

scheduler.getListenerManager().addSchedulerListener(new MySchedulerListener());

  • 8
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Quartz是一个强大的作业调度框架,可以用来实现定时任务。下面是Quartz基本使用方法: 1. 引入Quartz依赖 在项目的pom.xml文件中添加Quartz的依赖: ``` <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.3.2</version> </dependency> ``` 2. 配置Scheduler 在应用程序中创建一个Scheduler实例,用于调度作业。可以使用StdSchedulerFactory类创建一个Scheduler实例: ``` Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); ``` 3. 创建Job 创建一个实现了Job接口的类,并实现execute方法,该方法中实现需要执行的业务逻辑。 ``` public class MyJob implements Job { public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { // 业务逻辑 } } ``` 4. 创建JobDetail 创建一个JobDetail实例,用于描述Job的实现类及其它相关属性。 ``` JobDetail jobDetail = JobBuilder.newJob(MyJob.class).withIdentity("job1", "group1").build(); ``` 其中,withIdentity方法用于指定Job的名称和所属的组。 5. 创建Trigger 创建一个Trigger实例,用于描述Job的触发条件。 ``` Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").startNow().withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(10).repeatForever()).build(); ``` 其中,withIdentity方法用于指定Trigger的名称和所属的组,startNow方法用于指定Trigger的启动时间,withSchedule方法用于指定Trigger的调度策略,这里使用SimpleScheduleBuilder实现一个简单的定时调度策略,每隔10秒执行一次。 6. 调度Job 将JobDetail和Trigger传递给Scheduler的scheduleJob方法,用于调度Job。 ``` scheduler.scheduleJob(jobDetail, trigger); ``` 7. 启动Scheduler 使用Scheduler的start方法启动Scheduler。 ``` scheduler.start(); ``` 通过以上步骤,就可以使用Quartz实现简单的定时任务调度了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

faramita_of_mine

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值