Quartz2.x学习笔记(二):存储与持久化

4 篇文章 0 订阅
Quartz的存储与持久化
在默认情况下Quartz将任务调度的运行信息保存在内存中,这种方法提供了最佳的性能,因为内存中数据访问最快。不足之处是缺乏数据的持久性,当程序路途停止或系统崩溃时,所有运行的信息都会丢失。
而如果采用数据库存储的方式,那么如果调度执行到一半退出,再次运行可以通过方法恢复调度,从原来的地方开始执行。(如果调度10次,到第4次退出,那么卡可以从第5次继续执行)
下面是RAMjobStore和 jdbcjobstore的区别(摘自网络):

类型
优点
缺点
RAMJobStore
不要外部数据库,配置容易,运行速度快
因为调度程序信息是存储在被分配给 JVM的内存里面,所以,当应用程序停止运行时,所有调度信息将被丢失。另外因为存储到 JVM内存里面,所以可以存储多少个 JobTrigger将会受到限制
jdbcjobstore
支持集群,因为所有的任务信息都会保存到数据库中,可以控制事物,还有就是如果应用服务器关闭或者重启,任务信息都不会丢失,并且可以恢复因服务器关闭或者重启而导致执行失败的任务
运行速度的快慢取决与连接数据库的快慢

其实在Quartz的完整发布包的src\org\quartz该路径下就有quartz.properties的配置文件。如果我们配置了它,新的配置将会覆盖Quartz默认的配置。
在src下新增 quartz.properties文件,内容如下:
# Default Properties file for use by StdSchedulerFactory
# to create a Quartz Scheduler Instance, if a different
# properties file is not explicitly specified.
#

#集群配置
org.quartz.scheduler.instanceName: DefaultQuartzScheduler
org.quartz.scheduler.rmi.export: false
org.quartz.scheduler.rmi.proxy: false
org.quartz.scheduler.wrapJobExecutionInUserTransaction: false
#调度器的线程池配置
org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 10
org.quartz.threadPool.threadPriority: 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread: true

org.quartz.jobStore.misfireThreshold: 60000
#org.quartz.jobStore.misfireThreshold: 1000
#Quartz默认配置 保存到内存
#org.quartz.jobStore.class: org.quartz.simpl.RAMJobStore

#注释掉上面的默认配置
#持久化配置  即保存到数据库
org.quartz.jobStore.class:org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass:org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.useProperties:true
#数据库表前缀
org.quartz.jobStore.tablePrefix:qrtz_
org.quartz.jobStore.dataSource:qzDS

#============================================================================
# Configure Datasources
#============================================================================
JDBC驱动

org.quartz.dataSource.qzDS.driver:com.mysql.jdbc.Driver
org.quartz.dataSource.qzDS.URL:jdbc:mysql://localhost:3306/quartztest
org.quartz.dataSource.qzDS.user:root
org.quartz.dataSource.qzDS.password:123456
org.quartz.dataSource.qzDS.maxConnection:10
这里我使用的是 mysql,数据库用户和密码自己修改。
在Quartz的完整发布包的docs/dbTables目录下拥有对应不同数据库的SQL脚本,这里我导入了tables_mysql_innodb.sql,完成后如下:

编写测试类:
package com.Howard.test07;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class MyJob implements Job{

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String date = format.format(new Date());
        //每调度一次打印时间
        System.out.println("作业调度:"+date);

    }

}
package com.Howard.test07;

import java.util.List;

import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.StdSchedulerFactory;

public class JDBCJobStoreTest {
    public static void JobRun() throws SchedulerException, InterruptedException {

        SchedulerFactory factory = new StdSchedulerFactory();

        Scheduler scheduler = factory.getScheduler();

        //触发器类型
        SimpleScheduleBuilder builder = SimpleScheduleBuilder
                // 设置执行次数
                .repeatSecondlyForTotalCount(10, 3);
//                .withRepeatCount(10);


        JobDetail jobDetail = JobBuilder.newJob(MyJob.class)
                .withIdentity("job_1", "group_1")
                .build();

        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("trigger_1", "group_1")
                .startNow()
                .withSchedule(builder)
//                .withSchedule(SimpleScheduleBuilder.simpleSchedule()
//                         .withIntervalInSeconds(3)
//                          .withRepeatCount(10))
                .build();

        scheduler.scheduleJob(jobDetail, trigger);

        scheduler.start();

        Thread.sleep(10000);

        scheduler.shutdown();

    }

    public static void restoreJob() throws SchedulerException, InterruptedException{
        SchedulerFactory factory = new StdSchedulerFactory();
        Scheduler scheduler = factory.getScheduler();

         JobKey jobKey = new JobKey("job_1", "group_1");
         List<? extends Trigger> triggersOfJob = scheduler.getTriggersOfJob(jobKey);

         if(triggersOfJob.size()>0){
             for(Trigger t:triggersOfJob){
                 if(t instanceof SimpleTrigger || t instanceof CronTrigger){

                     scheduler.resumeJob(jobKey);
                 }
             }
         }

        scheduler.start();
    }


    public static void main(String[] args) throws SchedulerException, InterruptedException {
        //先注释第二个方法,执行第一个,看结果 之后注释第一个方法 执行第二个方法
        JobRun();
//        restoreJob();

    }
}
这里注意main函数里先注释掉第二个方法,执行第一个方法,结果如下:

由于我设置了10秒后关闭调度 所以只执行了4次(原本执行10次 隔3秒一次)
查看数据库表qrtz_simple_triggers:

这时注释第一个方法,使用第二个方法,恢复执行,结果如下:

执行完了剩余的6次。
(这里我quartz.properties 的其中一项配置org.quartz.jobStore.misfireThreshold: 60000 我改为了1000执行的,默认60000,如果用默认的,在短时间内你恢复job会发现时间有些错乱,其实这是正常的 这是Quartz的mixfire机制在搞鬼。相关机制的信息可以百度找找资料分析。这里给个misfire处理规则网址: https://my.oschina.net/chenleijava/blog/109904
运行完成后 会发现数据库里的job信息不见了,其实对于Cron和Simple类型,Simple类型的如果JobDetail没有设置.storeDurably(true),则job在运行完成之后会在数据库中删除。
注:如果数据库里存在了job或者trigger的名称的数据比如job_1,那么如果再start一个schedule关于jobdetail名字为job_1,是会报错的。因为数据库里已经存在该信息,无法再次存储。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值