quartz入门

本文介绍的是不与spring整合的quartz的使用。

代码(基于quartz2.3.0版本):

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

import java.util.Date;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;

public class QuartzTest {

    public static void main(String[] args) {
        try {
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
            JobDetail jobDetail = JobBuilder.newJob(SimpleQuartzJob.class).withIdentity("jobDetail", "jobDetailGroup")
                    .build();

            // 立即执行,5秒间隔无限制重复:
            Trigger trigger = TriggerBuilder.newTrigger()//
                    .withIdentity("myTrigger", "myTriggerGroup")
                    // 每5s执行一次任务
                    .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(5)).startNow().build();

            // 从现在开始10秒后执行一次:
            Date date = new Date();
            trigger = TriggerBuilder.newTrigger().startAt(new Date(date.getTime() + 10 * 1000)).build();

            // 从现在开始立即执行,每5秒重复,直到30秒后:
            Date date1 = new Date();
            trigger = TriggerBuilder.newTrigger().withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(5))
                    .startNow().endAt(new Date(date1.getTime() + 30 * 1000)).build();

            scheduler.scheduleJob(jobDetail, trigger);
            // fire triggers
            scheduler.start();
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }
}

public class SimpleQuartzJob implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println(context);
    }
}

quartz主要用到3个接口:Scheduler接口、JobDetail接口以及Trigger接口。

上面代码用StdSchedulerFactory的getDefaultScheduler()静态方法获取Scheduler实例(内部实现是创建StdSchedulerFactory工厂对象之后再获取Scheduler对象),用JobBuilder和TriggerBuilder的一系列方法获得JobDetail实例和Trigger实例,再把JobDetail实例和Trigger实例绑定到Scheduler实例上,然后调用Scheduler实例的start()方法触发定时器。

值得注意的是,JobBuilder的newJob(Class <? extends Job> jobClass)静态方法中要传的Class对象对应的org.quartz.Job实现类必须是public的,实测用内部类不行。

在本例中,获取Trigger对象时,TriggerBuilder对象的withSchedule(ScheduleBuilder scheBuilder)方法传入的参数是SimpleScheduleBuilder实例,这样将产生一个SimpleTrigger实例,这个实例只能满足基本情况。如果使用情况更复杂的话,需要使用CronTrigger,在withSchedule()方法中传入一个CronScheduleBuilder实例即可。SimpleTrigger和CronTrigger是Trigger接口的两个实现类。

CronTrigger利用用cron表达式可以满足各种各样的定时需求。关于cron表达式的用法,www.cnblogs.com/be-come/p/6165293.html讲的非常详细。

quartz存储与持久化:

quartz提供两种基本作业存储类型。第一种类型叫做RAMJobStore,第二种类型叫做JDBC作业存储。

在默认情况下quartz使用第一种存储类型,即将任务调度的运行信息保存在内存中,这种方法提供了最佳的性能,因为内存中数据访问最快。不足之处是缺乏数据的持久性,当程序路途停止或系统崩溃时,所有运行的信息都会丢失。

如果确实需要持久化任务调度信息,则可以把这些信息保存到数据库中,这样,系统崩溃重新启动后任务的调度信息会得以恢复。其实,如果是单机的quartz,那么保存任务调度信息基本没什么意义,保存任务调度信息最主要是用在quartz集群的情况下,在quartz集群中,我们希望在某一时刻只有一个服务器的quartz触发,具体是哪台服务器不要求。首先,需要我们手动建表,建表语句在quartz-2.3.0.jar包中,jar包解压后,在quartz-2.3.0orgquartzimpljdbcjobstore文件夹下可以找到在各种数据库中建表的sql脚本,从中挑选出对应的数据库脚本执行即可。之后,需要添加quartz.properties配置文件,内容如下:

#============================================================================
# Configure scheduler
#============================================================================
# org.quartz.scheduler.instanceName = Mscheduler
org.quartz.scheduler.instanceId=AUTO
#============================================================================
# Configure ThreadPool
#============================================================================
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount=20
org.quartz.threadPool.threadPriority=5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true
#============================================================================
# Configure JobStore
#============================================================================
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.useProperties=false
org.quartz.jobStore.dataSource=myDS
org.quartz.jobStore.tablePrefix=qrtz_
org.quartz.jobStore.isClustered=true
org.quartz.jobStore.maxMisfiresToHandleAtATime=1
org.quartz.jobStore.misfireThreshold=60000
#============================================================================
# Configure Datasources
#============================================================================
org.quartz.dataSource.myDS.driver=com.mysql.cj.jdbc.Driver
org.quartz.dataSource.myDS.URL=jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
org.quartz.dataSource.myDS.user=root
org.quartz.dataSource.myDS.password=123456
org.quartz.dataSource.myDS.maxConnections=5

org.quartz.threadPool.class用来配置quartz工作时用的线程池,默认是org.quartz.simpl.SimpleThreadPool

org.quartz.threadPool.threadCount用来配置线程池中的线程数量,默认为10个线程,优先级默认为5

org.quartz.jobStore.class配置成org.quartz.impl.jdbcjobstore.JobStoreTX,应用自己管理事务,如果想用应用服务器管理事务,则应配置成org.quartz.impl.jdbcjobstore.JobStoreCMT

org.quartz.jobStore.driverDelegateClass的值根据数据库不同而不同,mysql数据库对应org.quartz.impl.jdbcjobstore.StdJDBCDelegate,postgresql数据库对应org.quartz.impl.jdbcjobstore.PostgreSQLDelegate

org.quartz.jobStore.isClustered,是否启用集群,应用集群部署的话则值为true

解释一下这里为什么要配置数据源,因为是要把任务调度信息保存到数据库当中,所以肯定要配置数据源连接数据库。这里的数据源配置可以和应用的主数据源一致,也可以不一致,也可以共用一个配置。

原文地址:https://www.cnblogs.com/koushr/p/5873399.html