首页 > 代码库 > quartz入门

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.0\org\quartz\impl\jdbcjobstore文件夹下可以找到在各种数据库中建表的sql脚本,从中挑选出对应的数据库脚本执行即可。之后,需要添加quartz.properties配置文件,内容如下:

#============================================================================# Configure scheduler#============================================================================# org.quartz.scheduler.instanceName = Mschedulerorg.quartz.scheduler.instanceId=AUTO#============================================================================# Configure ThreadPool#============================================================================org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPoolorg.quartz.threadPool.threadCount=20org.quartz.threadPool.threadPriority=5org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true#============================================================================# Configure JobStore#============================================================================org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTXorg.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegateorg.quartz.jobStore.useProperties=falseorg.quartz.jobStore.dataSource=myDSorg.quartz.jobStore.tablePrefix=qrtz_org.quartz.jobStore.isClustered=trueorg.quartz.jobStore.maxMisfiresToHandleAtATime=1org.quartz.jobStore.misfireThreshold=60000#============================================================================# Configure Datasources#============================================================================org.quartz.dataSource.myDS.driver=com.mysql.cj.jdbc.Driverorg.quartz.dataSource.myDS.URL=jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTCorg.quartz.dataSource.myDS.user=rootorg.quartz.dataSource.myDS.password=123456org.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

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

quartz入门