quartz使用---入门使用

概念

quartz;定时器。可以比较专业的解决业务中的定时任务。例如每周定时生成报告,每隔固定时间进行数据分析等。其中一类是固定时间执行一次或者永久性的固定时间点执行任务;另一类是按照cron规则(按照日历规定每隔一定时间)执行任务。

使用

1.下载jar或者maven管理

<!-- quartz spring 3.1以上才支持quartz 2.2.1 -->
<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
</dependency>
<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz-jobs</artifactId>
</dependency>
<!-- end quartz -->

2.属性文件quartz.property

#最基本的属性文件
org.quartz.scheduler.instanceName = MyScheduler
org.quartz.threadPool.threadCount = 3
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore


#实际项目的属性文件
#==============================================================  
#Configure Main Scheduler Properties  
#==============================================================   
org.quartz.scheduler.instanceName = TestScheduler1
org.quartz.scheduler.instanceId = AUTO
#==============================================================  
#Configure ThreadPool  
#==============================================================   
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 5
org.quartz.threadPool.threadPriority = 5
#==============================================================  
#Configure JobStore  
#==============================================================   
org.quartz.jobStore.misfireThreshold = 60000
#use database to store quartz task
#这个是使用事务来保存任务信息,重启应用,任务信息不回丢失。
#org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
#use random access memory to store quartz 
#使用内存策略保存定时任务,当程序重启时,之前运行的任务会重启,之前任务的日志消失。
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
# \u9A71\u52A8\u5668\u65B9\u8A00
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#org.quartz.jobStore.tablePrefix = QRTZ_
#org.quartz.jobStore.useProperties=true
#这个dataSource的值,是自己定义的;随便取名,但是记得在后面配置DataSource时,注意跟这里保持一致。
#org.quartz.jobStore.dataSource=myQuartzDB

#org.quartz.jobStore.isClustered = true
#org.quartz.jobStore.clusterCheckinInterval = 15000

#==============================================================
# Configure Datasources  
#==============================================================
#我自己用的是sqlserver,所以使用了sqlserver的驱动器
#这里注意下,myQuartzDB和上边的org.quartz.jobStore.dataSource=myQuartzDB
#是同一个名称,这个名称可以自己定义
#org.quartz.dataSource.myQuartzDB.driver:com.microsoft.sqlserver.jdbc.SQLServerDriver
#org.quartz.dataSource.myQuartzDB.URL:jdbc:sqlserver://192.168.176.170:1433;SelectMethod=cursor;databaseName=TMSDB;integratedSecurity=false
#org.quartz.dataSource.myQuartzDB.user:sdgl
#org.quartz.dataSource.myQuartzDB.password:sdgl
#org.quartz.dataSource.myQuartzDB.maxConnections:10

3. quartz中主要包含三个对象:job、trigger、scheduler 。其中job()包含定时任务的任务信息。trigger(触发器)包含的是任务何时执行的规则信息。scheduler(调度器)负责调用job和trigger,使定时任务执行起来。

    //
    public class MyQuartzJob implements Job {
    private static Logger logger = LoggerFactory.getLogger(MyQuartzJob.class);

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        // TODO Auto-generated method stub
        System.out.println("任务成功运行,时间为:===" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        // JobDataMap jdm = context.getMergedJobDataMap();
        JobDetailImpl jdi = (JobDetailImpl) context.getJobDetail();
        //获取JobKey:
        JobKey jk = jdi.getKey();
        System.out.println("jk.getName():" + jk.getName());
        System.out.println("jk.getGroup():" + jk.getGroup());

        System.out.println("JobDetail jdi.getName():" + jdi.getName());
        // JobDetailImpl scheduleJob = (JobDetailImpl)
        // context.getMergedJobDataMap().get("scheduleJob");
        // System.out.println("任务名称 = [" + scheduleJob.getName() + "]");
    }
}

先来个最简单的运行实例:

 import org.quartz.Scheduler;
 import org.quartz.SchedulerException;
 import org.quartz.impl.StdSchedulerFactory;
 import static org.quartz.JobBuilder.*;
 import static org.quartz.TriggerBuilder.*;
 import static org.quartz.SimpleScheduleBuilder.*;
 //注意这里用的是静态导入!!!!当然也可以为了方便查看类的包引用情况,改为非静态导入

 public class QuartzTest {

  public static void main(String[] args) {

      try {
          // 从工厂类中获取一个调度器。
          Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

          // 启动
          scheduler.start();
         // 定义job的jobDetail,并关联到我们自己定义的job类
          JobDetail job = newJob(MyQuartzJob .class)
              .withIdentity("job1", "group1")
              .build();

          // 设置让程序运行时立即触发job,并且每四十秒运行一次,永久运行下去,知道我们停止定时器
          Trigger trigger = newTrigger()
              .withIdentity("trigger1", "group1")
              .startNow()
                    .withSchedule(simpleSchedule()
                      .withIntervalInSeconds(40)
                      .repeatForever())            
              .build();

          // 调度器调用job和trigger
          scheduler.scheduleJob(job, trigger);
          //在调用shutdown()之前,给job的触发和执行预留一些时间
          Thread.sleep(60000)
          ///60秒结束,执行shutdown
          scheduler.shutdown();

      } catch (SchedulerException se) {
          se.printStackTrace();
      }
  }
}

这样就是一个最简单的定时器。

Quartz API

Quartz API的关键接口是:

  • Scheduler - 与调度程序交互的主要API。
  • Job - 由希望由调度程序执行的组件实现的接口。
  • JobDetail - 用于定义作业的实例。
  • Trigger(即触发器) - 定义执行给定作业的计划的组件。
  • JobBuilder - 用于定义/构建JobDetail实例,用于定义作业的实例。
  • TriggerBuilder - 用于定义/构建触发器实例。

Scheduler的生命期,从SchedulerFactory创建它时开始,到Scheduler调用shutdown()方法时结束;Scheduler被创建后,可以增加、删除和列举Job和Trigger,以及执行其它与调度相关的操作(如暂停Trigger)。但是,Scheduler只有在调用start()方法后,才会真正地触发trigger(即执行job)

Quartz提供的“builder”类,可以认为是一种领域特定语言(DSL,Domain Specific Language)(这种级联的API非常方便用户使用,大家以后写对外接口时也可以使用这种方式)。例如

 // define the job and tie it to our HelloJob class
  JobDetail job = newJob(HelloJob.class)
      .withIdentity("myJob", "group1") // name "myJob", group "group1"
      .build();

  // Trigger the job to run now, and then every 40 seconds
  Trigger trigger = newTrigger()
      .withIdentity("myTrigger", "group1")
      .startNow()
      .withSchedule(simpleSchedule()
          .withIntervalInSeconds(40)
          .repeatForever())            
      .build();

  // Tell quartz to schedule the job using our trigger
  sched.scheduleJob(job, trigger);

定义job的代码使用的是从JobBuilder静态导入的方法。同样,定义trigger的代码使用的是从TriggerBuilder静态导入的方法 。 另外,也导入了SimpleSchedulerBuilder类的静态方法;

DSL的静态导入可以通过以下导入语句来实现:

import static org.quartz.JobBuilder.*;
import static org.quartz.SimpleScheduleBuilder.*;
import static org.quartz.CronScheduleBuilder.*;
import static org.quartz.CalendarIntervalScheduleBuilder.*;
import static org.quartz.TriggerBuilder.*;
import static org.quartz.DateBuilder.*;

SchedulerBuilder接口的各种实现类,可以定义不同类型的调度计划(schedule);

DateBuilder类包含很多方法,可以很方便地构造表示不同时间点的java.util.Date实例(如定义下一个小时为偶数的时间点,如果当前时间为9:43:27,则定义的时间为10:00:00)。
Job和Trigger
一个job就是一个实现了Job接口的类,该接口只有一个方法:

Job接口:

  package org.quartz;

  public interface Job {

    public void execute(JobExecutionContext context)
      throws JobExecutionException;
  }

当Job的一个trigger被触发(稍后会讲到)时,execute()方法由调度程序的一个工作线程调用。传递给execute()方法的JobExecutionContext对象向作业实例提供有关其“运行时”环job的一个trigger被触发后(稍后会讲到),execute()方法会被scheduler的一个工作线程调用;传递给execute()方法的JobExecutionContext对象中保存着该job运行时的一些信息 ,执行job的scheduler的引用,触发job的trigger的引用,JobDetail对象引用,以及一些其它信息。

JobDetail对象是在将job加入scheduler时,由客户端程序(你的程序)创建的。它包含job的各种属性设置,以及用于存储job实例状态信息的JobDataMap。本节是对job实例的简单介绍,更多的细节将在下一节讲到。

Trigger用于触发Job的执行。当你准备调度一个job时,你创建一个Trigger的实例,然后设置调度相关的属性。Trigger也有一个相关联的JobDataMap,用于给Job传递一些触发相关的参数。Quartz自带了各种不同类型的Trigger,最常用的主要是SimpleTrigger和CronTrigger。

SimpleTrigger主要用于一次性执行的Job(只在某个特定的时间点执行一次),或者Job在特定的时间点执行,重复执行N次,每次执行间隔T个时间单位。CronTrigger在基于日历的调度上非常有用,如“每个星期五的正午”,或者“每月的第十天的上午10:15”等。

为什么既有Job,又有Trigger呢?很多任务调度器并不区分Job和Trigger。有些调度器只是简单地通过一个执行时间和一些job标识符来定义一个Job;其它的一些调度器将Quartz的Job和Trigger对象合二为一。在开发Quartz的时候,我们认为将调度和要调度的任务分离是合理的。在我们看来,这可以带来很多好处。

例如,Job被创建后,可以保存在Scheduler中,与Trigger是独立的,同一个Job可以有多个Trigger;这种松耦合的另一个好处是,当与Scheduler中的Job关联的trigger都过期时,可以配置Job稍后被重新调度,而不用重新定义Job;还有,可以修改或者替换Trigger,而不用重新定义与之关联的Job。

Key
将Job和Trigger注册到Scheduler时,可以为它们设置key,配置其身份属性。Job和Trigger的key(JobKey和TriggerKey)可以用于将Job和Trigger放到不同的分组(group)里,然后基于分组进行操作。同一个分组下的Job或Trigger的名称必须唯一,即一个Job或Trigger的key由名称(name)和分组(group)组成。

猜你喜欢

转载自blog.csdn.net/Jatham/article/details/81346631