Quartz学习笔记:基础知识

Quartz学习笔记:基础知识

引入Quartz

关于任务调度

  关于任务调度,Java.util.Timer是最简单的一种实现任务调度的方法,简单的使用如下:

import java.util.Timer;
import java.util.TimerTask;

public class TimerTest {
    public static void main(String[] args) {
        Timer timer = new Timer();
        long delay = 1000;    //延时多少秒开始执行
        long period =1000;    //执行周期
        timer.schedule(new MyTask(),delay,period);
    }
}

class MyTask extends TimerTask{

    @Override
    public void run() {
        System.out.println("Hello World");
    }
}

  使用 Timer 实现任务调度的核心类是 Timer 和 TimerTask。其中 Timer 负责设定 TimerTask 的起始与间隔执行时间。使用者只需要创建一个 TimerTask 的继承类,实现自己的 run 方法,然后将其丢给 Timer 去执行即可。

   Timer 的设计核心是一个 TaskList 和一个 TaskThread。Timer 将接收到的任务丢到自己的 TaskList 中,TaskList 按照 Task 的最初执行时间进行排序。TimerThread 在创建 Timer 时会启动成为一个守护线程。这个线程会轮询所有任务,找到一个最近要执行的任务,然后休眠,当到达最近要执行任务的开始时间点,TimerThread 被唤醒并执行该任务。之后 TimerThread 更新最近一个要执行的任务,继续休眠。

引入Quartz

    

  Quartz 是一个完全由 Java 编写开源作业调度框架,为在 Java 应用程序中进行作业调度提供了简单却强大的机制。

Quartz的核心概念

  我们需要明白 Quartz 的几个核心概念,这样理解起 Quartz 的原理就会变得简单了。

    

  1. Job 表示一个工作,要执行的具体内容。类似于TimerTask类。需要实现方法 void execute(JobExecutionContext context) 
  2. JobDetail 表示一个具体的可执行的调度程序,Job 是这个可执行程调度程序所要执行的内容,另外 JobDetail 还包含了这个任务调度的方案和策略。 
  3. Trigger 代表一个调度参数的配置,什么时候去调。 
  4. Scheduler 代表一个调度容器。类似于Timer类。一个调度容器中可以注册多个 JobDetail 和 Trigger。当 Trigger 与 JobDetail 组合,就可以被 Scheduler 容器调用。

  

快速开始

Scheduler(调度器)

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

  //1、通过工程创建调度器
  SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();
  Scheduler sched = schedFact.getScheduler();
  //2、启动调度器
  sched.start();

Job、JobDetail(任务及任务细节)

  使用者只需要创建一个 Job 的子类,实现 execute 方法。JobDetail 负责封装 Job 以及 Job 的属性,并将其提供给 Scheduler 作为参数。每次 Scheduler 执行任务时,首先会创建一个 Job 的实例,然后再调用 execute 方法执行。Quartz 没有为 Job 设计带参数的构造函数,因此需要通过额外的 JobDataMap 来存储 Job 的属性。JobDataMap 可以存储任意数量的 Key,Value 对。

//[!]存储普通类型
jobDetail.getJobDataMap().put("myDescription", "my job description"); 
jobDetail.getJobDataMap().put("myValue", 1998); 
//[!]存储对象
ArrayList<String> list = new ArrayList<String>(); 
list.add("item1"); 
jobDetail.getJobDataMap().put("myArray", list);

  JobDataMap中的数据获取可以通过下面这种方式:

public class JobDataMapTest implements Job {
 
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        //从context中获取instName,groupName以及dataMap
        String instName = context.getJobDetail().getName();
        String groupName = context.getJobDetail().getGroup();
        JobDataMap dataMap = context.getJobDetail().getJobDataMap();
        //从dataMap中获取myDescription,myValue以及myArray
        String myDescription = dataMap.getString("myDescription");
        int myValue = dataMap.getInt("myValue");
        ArrayList<String> myArray = (ArrayListlt;Strin>) dataMap.get("myArray");
        System.out.println("
                Instance =" + instName + ", group = " + groupName
                + ", description = " + myDescription + ", value =" + myValue
                + ", array item0 = " + myArray.get(0));
 
    }
}

Trigger(触发器)

  Trigger 的作用是设置调度策略。Quartz 设计了多种类型的 Trigger,其中最常用的是 SimpleTrigger 和 CronTrigger。

  • SimpleTrigger 适用于在某一特定的时间执行一次,或者在某一特定的时间以某一特定时间间隔执行多次。上述功能决定了 SimpleTrigger 的参数包括 start-time, end-time, repeat count, 以及 repeat interval。
  • CronTrigger 的用途更广,相比基于特定时间间隔进行调度安排的 SimpleTrigger,CronTrigger 主要适用于基于日历的调度安排。例如:每星期二的 16:38:10 执行,每月一号执行,以及更复杂的调度安排等。

  CronTrigger的使用如下:

CronTrigger cronTrigger = new CronTrigger("myTrigger", "myGroup"); 
try { 
    cronTrigger.setCronExpression("0 0/30 20-13 ? * MON-WED,SAT"); 
} catch (Exception e) { 
    e.printStackTrace(); 
}

Listener(监听器)

  Quartz 还提供了 listener 的功能。主要包含三种 listener:

  • JobListener
  • TriggerListener
  • SchedulerListener

  当系统发生故障,相关人员需要被通知时,Listener 便能发挥它的作用。最常见的情况是,当任务被执行时,系统发生故障,Listener 监听到错误,立即发送邮件给管理员

  关于监听器的问题,我们会在之后认真讨论。

JobStores

  Quartz 的另一显著优点在于持久化,即将任务调度的相关数据保存下来。这样,当系统重启后,任务被调度的状态依然存在于系统中,不会丢失。默认情况下,Quartz 采用的是 org.quartz.simpl.RAMJobStore,在这种情况下,数据仅能保存在内存中,系统重启后会全部丢失。若想持久化数据,需要采用 org.quartz.simpl.JDBCJobStoreTX

  第一步:创建数据库及表。

  第二部:配置数据源。

# Configure ThreadPool 
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool 
org.quartz.threadPool.threadCount =  5 
org.quartz.threadPool.threadPriority = 4 
 
# Configure Datasources 
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX 
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate 
org.quartz.jobStore.dataSource = db2DS 
org.quartz.jobStore.tablePrefix = QRTZ_ 
 
org.quartz.dataSource.db2DS.driver = com.ibm.db2.jcc.DB2Driver 
org.quartz.dataSource.db2DS.URL = jdbc:db2://localhost:50001/sched 
org.quartz.dataSource.db2DS.user = quartz 
org.quartz.dataSource.db2DS.password = passw0rd 
org.quartz.dataSource.db2DS.maxConnections = 5

  使用时只需要将 quatz.properties 放在 classpath 下面,不用更改一行代码,再次运行之前的任务调度实例,trigger、job 等信息便会被记录在数据库中。

一个调度任务的创建

  最后我们再来回顾一下,我们一个调度系统的增加一个任务的全流程:

  //1、定义JobDetail,注意需要实现定义Job,实现execute方法即可
  JobDetail job = newJob(HelloJob.class)
      .withIdentity("job1", "group1")
      .build();

  //2、定义触发器,即任务的执行策略
  Trigger trigger = newTrigger()
      .withIdentity("trigger1", "group1")
      .startNow()
            .withSchedule(simpleSchedule()
              .withIntervalInSeconds(40)
              .repeatForever())            
      .build();

  //3、告诉Quartz去调度使用了trigger触发器的job
  scheduler.scheduleJob(job, trigger);

 参考链接

原文地址:https://www.cnblogs.com/MrSaver/p/11799966.html