quartz2.3.0(十五)執行、暫停、繼續執行、清除,花式操作數據庫中持久化的job任務


#############################################################################################################################################

                      1、 建立數據庫11張表

#############################################################################################################################################

先在數據庫中建立quartz需要的11張表(我這里用的是Oracle數據庫),根據不同的數據庫quartz分別提供了不同的初始化sql文件,sql文件路徑在 quartz-2.3.0-SNAPSHOT-0724\src\org\quartz\impl\jdbcjobstore下:

 1 tables_cloudscape.sql
 2 tables_cubrid.sql
 3 tables_db2.sql
 4 tables_db2_v8.sql
 5 tables_db2_v72.sql
 6 tables_db2_v95.sql
 7 tables_derby.sql
 8 tables_derby_previous.sql
 9 tables_firebird.sql
10 tables_h2.sql
11 tables_hsqldb.sql
12 tables_hsqldb_old.sql
13 tables_informix.sql
14 tables_mysql.sql
15 tables_mysql_innodb.sql
16 tables_oracle.sql
17 tables_pointbase.sql
18 tables_postgres.sql
19 tables_sapdb.sql
20 tables_solid.sql
21 tables_sqlServer.sql
22 tables_sybase.sql

 

#############################################################################################################################################

                      2、 配置定時器數據庫等相關配置:quartz.properties

#############################################################################################################################################

#============================================================================
# Configure Main Scheduler Properties  
#============================================================================
#調度器實例名稱
org.quartz.scheduler.instanceName: SchedulerJoyce0725
org.quartz.scheduler.instanceId: InstanceJoyce0725

#============================================================================
# Configure ThreadPool  
#============================================================================
org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount: 5
org.quartz.threadPool.threadPriority: 1

#============================================================================
# 配置Oracle數據庫,命名dataSource為myDS
#============================================================================
### 支持PostgreSQL數據庫
###org.quartz.dataSource.myDS.driver=org.postgresql.Driver
###org.quartz.dataSource.myDS.URL=jdbc:postgresql://localhost:5432/quartz
org.quartz.dataSource.myDS.driver=oracle.jdbc.driver.OracleDriver
org.quartz.dataSource.myDS.URL=jdbc:oracle:thin:@localhost:1521:orcl
org.quartz.dataSource.myDS.user=zhuwen
org.quartz.dataSource.myDS.password=ZHUwen12
org.quartz.dataSource.myDS.maxConnections=5
org.quartz.dataSource.myDS.validationQuery=select 0 FROM DUAL

#============================================================================
# 配置job任務存儲策略,指定一個叫myDS的dataSource
#============================================================================
org.quartz.jobStore.misfireThreshold: 60000
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
### 支持PostgreSQL數據庫
###org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
### 支持Oracle數據庫
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.oracle.OracleDelegate
org.quartz.jobStore.useProperties=false
org.quartz.jobStore.dataSource=myDS
org.quartz.jobStore.tablePrefix=QRTZ_
org.quartz.jobStore.isClustered=true

 

################################################################################################################

       3、 11張表不同定時方式分別存儲了不同數據到不同的表

################################################################################################################

ScheduleBuilder是trigger觸發器的觸發規則定制類,旗下有4種觸發器實現類:  CalendarIntervalScheduleBuilder、CronScheduleBuilder、DailyTimeIntervalScheduleBuilder、SimpleScheduleBuilder。

這里演示了CronScheduleBuilder和SimpleScheduleBuilder兩種定時方式,分別執行后面的StoreSimpleTrigger2OracleExample.java 和 StoreCronTrigger2OracleExample.java 就能看到數據庫如下的差別:

這4中實現類在數據庫的11張表中存儲一個任務時,分別會產生不一樣的數據,用顏色標注insert語句如下:

select * from qrtz_blob_triggers;   --沒有insert語句就表示此表一直沒有數據

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

select * from qrtz_calendars;
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

select * from qrtz_cron_triggers;

Insert into QRTZ_CRON_TRIGGERS (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,CRON_EXPRESSION,TIME_ZONE_ID)
values ('SchedulerJoyce0725','cronTrigger','cronGroup1','0/5 * * * * ?','Asia/Shanghai');

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

select * from qrtz_fired_triggers;
Insert into QRTZ_FIRED_TRIGGERS (SCHED_NAME,ENTRY_ID,TRIGGER_NAME,TRIGGER_GROUP,INSTANCE_NAME,FIRED_TIME,SCHED_TIME,PRIORITY,STATE,JOB_NAME,JOB_GROUP,IS_NONCONCURRENT,REQUESTS_RECOVERY)
values ('SchedulerJoyce0725','InstanceJoyce07251564061848994','cronTrigger','cronGroup1','InstanceJoyce0725',1564061855002,1564061855000,5,'EXECUTING','simpleRecoveryJob','cronGroup1','0','0');  --每一次遠程啟動時ENTRY_ID總是會變一變

Insert into QRTZ_FIRED_TRIGGERS (SCHED_NAME,ENTRY_ID,TRIGGER_NAME,TRIGGER_GROUP,INSTANCE_NAME,FIRED_TIME,SCHED_TIME,PRIORITY,STATE,JOB_NAME,JOB_GROUP,IS_NONCONCURRENT,REQUESTS_RECOVERY) values ('SchedulerJoyce0725','InstanceJoyce07251564066439267','simpleTriger1','simpleGroup','InstanceJoyce0725',1564066446293,1564066451270,5,'ACQUIRED',null,null,'0','0');  

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

select * from qrtz_job_details;
Insert into QRTZ_JOB_DETAILS (SCHED_NAME,JOB_NAME,JOB_GROUP,DESCRIPTION,JOB_CLASS_NAME,IS_DURABLE,IS_NONCONCURRENT,IS_UPDATE_DATA,REQUESTS_RECOVERY,JOB_DATA)
values ('SchedulerJoyce0725','simpleRecoveryJob','cronGroup1',null,'org.quartz.examples.example15.SimpleRecoveryJob','0','0','0','0',
TO_BLOB(HEXTORAW('...'))|| TO_BLOB(HEXTORAW('...')));

Insert into QRTZ_JOB_DETAILS (SCHED_NAME,JOB_NAME,JOB_GROUP,DESCRIPTION,JOB_CLASS_NAME,IS_DURABLE,IS_NONCONCURRENT,IS_UPDATE_DATA,REQUESTS_RECOVERY,JOB_DATA)
values ('SchedulerJoyce0725','simpleJob1','simpleGroup',null,'org.quartz.examples.example15.SimpleRecoveryJob','0','0','0','1',
TO_BLOB(HEXTORAW('...'))|| TO_BLOB(HEXTORAW('...')));

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

select * from qrtz_locks;
Insert into qrtz_locks (SCHED_NAME,LOCK_NAME) values ('SchedulerJoyce0725','STATE_ACCESS');
Insert into qrtz_locks (SCHED_NAME,LOCK_NAME) values ('SchedulerJoyce0725','TRIGGER_ACCESS');

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

select * from qrtz_paused_trigger_grps;

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

select * from qrtz_scheduler_state;
Insert into qrtz_scheduler_state (SCHED_NAME,INSTANCE_NAME,LAST_CHECKIN_TIME,CHECKIN_INTERVAL)
values ('SchedulerJoyce0725','InstanceJoyce0725',1564061857522,7500);

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

select * from qrtz_simple_triggers;

Insert into QRTZ_SIMPLE_TRIGGERS (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,REPEAT_COUNT,REPEAT_INTERVAL,TIMES_TRIGGERED)

values ('SchedulerJoyce0725','simpleTriger1','simpleGroup',20,5000,2);

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
select * from qrtz_simprop_triggers;

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

select * from qrtz_triggers;
Insert into qrtz_triggers (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,JOB_NAME,JOB_GROUP,DESCRIPTION,NEXT_FIRE_TIME,PREV_FIRE_TIME,PRIORITY,TRIGGER_STATE,TRIGGER_TYPE,START_TIME,END_TIME,CALENDAR_NAME,MISFIRE_INSTR,JOB_DATA)
values ('SchedulerJoyce0725','cronTrigger','cronGroup1','simpleRecoveryJob','cronGroup1',null,1564061865000,1564061860000,5,'ACQUIRED','CRON',1564061849000,0,null,0, EMPTY_BLOB());

Insert into QRTZ_TRIGGERS (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,JOB_NAME,JOB_GROUP,DESCRIPTION,NEXT_FIRE_TIME,PREV_FIRE_TIME,PRIORITY,TRIGGER_STATE,TRIGGER_TYPE,START_TIME,END_TIME,CALENDAR_NAME,MISFIRE_INSTR,JOB_DATA) values ('SchedulerJoyce0725','simpleTriger1','simpleGroup','simpleJob1','simpleGroup',null,1564066451270,1564066446270,5,'ACQUIRED','SIMPLE',1564066441270,0,null,0, EMPTY_BLOB());

 

#############################################################################################################################################

                     4、  job任務類,SimpleRecoveryJob.java

#############################################################################################################################################

package org.quartz.examples.example15;

import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;

/**
 * 一個job作業。
 */
public class SimpleRecoveryJob implements Job {

    private static Logger LOG = LoggerFactory.getLogger(SimpleRecoveryJob.class);

    private static final String COUNT = "count";

    //必須要有public修飾的無參構造函數
    public SimpleRecoveryJob() {
    }

    //任務執行方法
    public void execute(JobExecutionContext context) throws JobExecutionException {

        JobKey jobKey = context.getJobDetail().getKey();

        // 如果由於“恢復”情況而重新執行作業,此方法將返回true。
        if (context.isRecovering()) {
            LOG.info("恢復作業:SimpleRecoveryJob: " + jobKey + " RECOVERING at " + new Date());
        } else {
            LOG.info("不恢復作業:SimpleRecoveryJob: " + jobKey + " starting at " + new Date());
        }

        JobDataMap data = context.getJobDetail().getJobDataMap();
        int count;
        if (data.containsKey(COUNT)) {
            count = data.getInt(COUNT);
        } else {
            count = 0;
        }
        count++;
        data.put(COUNT, count);

        LOG.info("SimpleRecoveryJob: " + jobKey + " done at " + new Date() + "\n Execution #" + count);

    }

}

 

 

#############################################################################################################################################

                      5、  簡單定時任務存儲到數據庫表,StoreSimpleTrigger2OracleExample.java

#############################################################################################################################################

package org.quartz.examples.example15;

import static org.quartz.DateBuilder.futureDate;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.SimpleScheduleBuilder.simpleSchedule;
import static org.quartz.TriggerBuilder.newTrigger;

import org.quartz.DateBuilder.IntervalUnit;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleTrigger;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 簡單定時任務存儲到數據庫表。
 * 存儲job任務到數據庫,這里打印的job任務都是:     不恢復作業……
 */
public class StoreSimpleTrigger2OracleExample {

    private static Logger LOG = LoggerFactory.getLogger(StoreSimpleTrigger2OracleExample.class);

    public void run(boolean inClearJobs, boolean inScheduleJobs) throws Exception {

        // 初始化調度器
        SchedulerFactory sf = new StdSchedulerFactory();
        Scheduler sched = sf.getScheduler();

        if (inClearJobs) {
            sched.clear();
            LOG.warn("***** Deleted existing jobs/triggers *****");
        }

        LOG.info("------- Initialization Complete -----------");

        if (inScheduleJobs) {

            LOG.info("------- Scheduling Jobs ------------------");

            String schedId = sched.getSchedulerInstanceId();

            // ========================================================
            // ============ job1
            // ========================================================
            int count = 1;
            JobDetail job = newJob(SimpleRecoveryJob.class).withIdentity("simpleJob" + count, "simpleGroup").requestRecovery() // 如果job執行過程中宕機,則job重新執行
                    .build();
            SimpleTrigger trigger = newTrigger().withIdentity("simpleTriger" + count, "simpleGroup")
                    .startAt(futureDate(1, IntervalUnit.SECOND))
                    .withSchedule(simpleSchedule().withRepeatCount(20).withIntervalInSeconds(5)).build();
            LOG.info(job.getKey() + " will run at: " + trigger.getNextFireTime() + " and repeat: "
                    + trigger.getRepeatCount() + " times, every " + trigger.getRepeatInterval() / 1000 + " seconds");
            sched.scheduleJob(job, trigger);
//
//            // ========================================================
//            // ============ job2
//            // ========================================================
//            count++;
//            job = newJob(SimpleRecoveryJob.class).withIdentity("job0724_" + count, schedId).requestRecovery() // 如果job執行過程中宕機,則job重新執行
//                    .build();
//            trigger = newTrigger().withIdentity("triger0724_" + count, schedId).startAt(futureDate(2, IntervalUnit.SECOND))
//                    .withSchedule(simpleSchedule().withRepeatCount(20).withIntervalInSeconds(5)).build();
//            LOG.info(job.getKey() + " will run at: " + trigger.getNextFireTime() + " and repeat: "
//                    + trigger.getRepeatCount() + " times, every " + trigger.getRepeatInterval() / 1000 + " seconds");
//            sched.scheduleJob(job, trigger);

        }

        LOG.info("------- Starting Scheduler ---------------");
        sched.start();
        try {
            Thread.sleep(3600L * 1000L);
        } catch (Exception e) {
            //
        }
        sched.shutdown();
        LOG.info("------- Shutdown Complete ----------------");
    }

    public static void main(String[] args) throws Exception {
        boolean clearJobs = true; // 是否清空job任務
        boolean scheduleJobs = true; // 是否調度任務

        for (String arg : args) {
            if (arg.equalsIgnoreCase("clearJobs")) {
                clearJobs = true;
            } else if (arg.equalsIgnoreCase("dontScheduleJobs")) {
                scheduleJobs = false;
            }
        }

        StoreSimpleTrigger2OracleExample example = new StoreSimpleTrigger2OracleExample();
        example.run(clearJobs, scheduleJobs);
    }
}

 

#############################################################################################################################################

                     6、  cron定義定時任務存儲到數據庫表,StoreCronTrigger2OracleExample.java

#############################################################################################################################################

package org.quartz.examples.example15;

import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;

import java.util.Date;

import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * cron定義定時任務存儲到數據庫表。
 * 存儲job任務到數據庫,這里打印的job任務都是:     不恢復作業……
 */
public class StoreCronTrigger2OracleExample {

    private static Logger LOG = LoggerFactory.getLogger(StoreCronTrigger2OracleExample.class);

    public void run(boolean inClearJobs) throws Exception {

        // 初始化調度器
        SchedulerFactory sf = new StdSchedulerFactory();
        Scheduler sched = sf.getScheduler();

        if (inClearJobs) {
            sched.clear();
            LOG.warn("***** Deleted existing jobs/triggers *****");
        }

        // ========================================================
        // ============ job1 每20秒執行一次,無限期重復
        // ========================================================
        JobDetail job = newJob(SimpleRecoveryJob.class).withIdentity("simpleRecoveryJob_Recovery", "cronGroup2")
                .requestRecovery() //如果job任務所在服務宕機了或由於其它原因job任務被中斷,請標記JobExecutionContext.isRecovering()=true。
                                   //讓我可以拿這個標記知道怎么去適配業務場景。
                                   //但是只有恢復任務后首次執行任務時,拿到Recovering標記值為true,此后該任務Recovering值又標記為了false。
                .build();
        //每5秒執行一次
        CronTrigger trigger = newTrigger().withIdentity("cronTrigger_Recovery", "cronGroup2").withSchedule(cronSchedule("0/5 * * * * ?")).build();
        Date ft = sched.scheduleJob(job, trigger);
        LOG.info(job.getKey() + " has been scheduled to run at: " + ft + " and repeat based on expression: "
                + trigger.getCronExpression());

        LOG.info("------- Starting Scheduler ---------------");
        sched.start();
        try {
            Thread.sleep(3600L * 1000L);
        } catch (Exception e) {
            //
        }

        // 暫停執行任務
        sched.pauseJob(job.getKey());
        LOG.info("調度器暫停執行定時器,主線程睡眠11秒!!!!會錯過執行job1的N次定時任務。模擬當定時器的執行線程由於搶不到CPU時間或其他事件錯過執行的情況。");
        Thread.sleep(11L * 1000L);
        // 繼續執行任務
        sched.resumeJob(job.getKey()); //當定時器得到繼續執行的命令時,被錯過執行的任務次數,就會按照misfire的定義去執行
        
        sched.shutdown();
        LOG.info("------- Shutdown Complete ----------------");
    }

    public static void main(String[] args) throws Exception {
        boolean clearJobs = false; // 是否清空job任務

        StoreCronTrigger2OracleExample example = new StoreCronTrigger2OracleExample();
        example.run(clearJobs);
    }
}

#############################################################################################################################################

                  7、  執行數據庫中的定時任務,RunOracleExistingJobExample.java

#############################################################################################################################################

package org.quartz.examples.example15;

import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 先運行ClusterExample.java,確定Oracle數據庫中已存在job任務.
 * 這里打印的job任務都是從數據庫表里恢復回來的,所以這些任務的第一次執行會打印:     恢復作業……
 * 此后job任務就只打印:不恢復作業……
 */
public class RunOracleExistingJobExample {

    private static Logger LOG = LoggerFactory.getLogger(RunOracleExistingJobExample.class);

    public void run(boolean inClearJobs) throws Exception {

        // 初始化調度器
        SchedulerFactory sf = new StdSchedulerFactory();
        Scheduler sched = sf.getScheduler();

        if (inClearJobs) {
            sched.clear();
            LOG.warn("***** Deleted existing jobs/triggers *****");
        }

        LOG.info("------- Starting Scheduler ---------------");
        sched.start();
        try {
            Thread.sleep(3600L * 1000L);
        } catch (Exception e) {
            //
        }
        
        sched.shutdown();
        LOG.info("------- Shutdown Complete ----------------");
    }

    public static void main(String[] args) throws Exception {
        boolean clearJobs = false; // 是否清空job任務,這里為不清空

        RunOracleExistingJobExample example = new RunOracleExistingJobExample();
        example.run(clearJobs);
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM