任务调度管理器Quartz漫谈

Posted yxz1025

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了任务调度管理器Quartz漫谈相关的知识,希望对你有一定的参考价值。

quartz中主要有Job、JobDetail、Scheduler构成

在你需要执行的任务中只要实现Job类,然后在execute中执行具体的任务即可。你定义了一个实现Job接口的类,这个类仅仅表明该job需要完成什么类型的任务.

首先,我们可以实现一个定时任务管理类ScheduleManager.java:

package com.realtech.model;

import org.quartz.CronScheduleBuilder;
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.TriggerBuilder;
import org.quartz.TriggerKey;

/**
 * 定时任务管理类
 * @author yuanxiaozhong
 * 
 */
public class ScheduleManager 

    /**
     * 任务工厂类
     */
    private  Scheduler scheduler;


    public void setScheduler(Scheduler scheduler) 
        this.scheduler = scheduler;
    

    /**
     * @Describe 添加一个任务
     * @param jobName 工作名称
     * @param groupName 组名称
     * @param cls 任务类名称
     * @param cronExpress 任务表达式
     */
    public void addJob(String jobName, String groupName, Class cls, String cronExpress)
        JobDetail jobDetail = JobBuilder.newJob(cls)
                .withIdentity(jobName, groupName)
                .build();
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpress);
        try 
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName, groupName)
                    .withSchedule(scheduleBuilder)
                    .build();
            scheduler.scheduleJob(jobDetail, trigger);
         catch (SchedulerException e) 
            System.out.println(e.getMessage());
            e.printStackTrace();
        
    

    /**
     * 修改一个任务的出发时间,使用默认的任务名称,任务组
     * @param jobName 工作名称
     * @param groupName 组名称
     * @param cronExpress 任务表达式
     */
    public void modifyJob(String jobName, String groupName, String cronExpress)
        TriggerKey triggerKey = TriggerKey.triggerKey(jobName, groupName);
        try 
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            if (trigger == null) 
                return;
            
            String oldExpress = trigger.getCronExpression();
            if (!oldExpress.equalsIgnoreCase(cronExpress)) 
                CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpress);
                trigger = trigger.getTriggerBuilder().withIdentity(triggerKey)
                        .withSchedule(scheduleBuilder)
                        .build();
                scheduler.rescheduleJob(triggerKey, trigger);
            
         catch (SchedulerException e) 
            // TODO Auto-generated catch block
            e.printStackTrace();
        
    

    /**
     * 暂停一个任务
     * @param jobName
     * @param groupName
     */
    public void pauseJob(String jobName, String groupName)
        JobKey jobKey = JobKey.jobKey(jobName, groupName);
        try 
            scheduler.pauseJob(jobKey);
         catch (SchedulerException e) 
            // TODO Auto-generated catch block
            e.printStackTrace();
        
    

    /**
     * 恢复一个任务
     * @param jobName
     * @param groupName
     */
    public void resumeJob(String jobName, String groupName)
        JobKey jobKey = JobKey.jobKey(jobName, groupName);
        try 
            scheduler.resumeJob(jobKey);
         catch (SchedulerException e) 
            e.printStackTrace();
        
    

    /**
     * 删除任务
     * @param jobName
     * @param groupName
     */
    public void deleteJob(String jobName, String groupName)
        JobKey jobKey = JobKey.jobKey(jobName, groupName);
        try 
            scheduler.deleteJob(jobKey);
         catch (SchedulerException e) 
            // TODO Auto-generated catch block
            e.printStackTrace();
        
    

    /**
     * 启动所有任务
     */
    public void startAll()
        try 
            scheduler.start();
         catch (SchedulerException e) 
            // TODO Auto-generated catch block
            e.printStackTrace();
        
    


如果你使用maven管理项目需要在src/main/resources下定义一个quartz.properties 文件,内容如下:

org.quartz.scheduler.instanceName = MyScheduler
org.quartz.threadPool.threadCount = 3
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore

让我们看看如何添加一个任务以及具体的执行流程

        /**
     * @Describe 添加一个任务
     * @param jobName 工作名称
     * @param groupName 组名称
     * @param cls 任务类名称
     * @param cronExpress 任务表达式
     */
    public void addJob(String jobName, String groupName, Class cls, String cronExpress)
        JobDetail jobDetail = JobBuilder.newJob(cls)
                .withIdentity(jobName, groupName)
                .build();
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpress);
        try 
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName, groupName)
                    .withSchedule(scheduleBuilder)
                    .build();
            scheduler.scheduleJob(jobDetail, trigger);
         catch (SchedulerException e) 
            System.out.println(e.getMessage());
            e.printStackTrace();
        
    

首先通过JobDetail创建一个对应的job实现类对象,并且指定任务名称和任务组,然后定义这个任务的执行时间周期,quartz提供了SimpleTrigger和 CronTriggers两种,前者执行一些简单的任务归类比如:

  CronTriggers往往比SimpleTrigger更有用,如果您需要基于日历的概念,而非SimpleTrigger完全指定的时间间隔,复发的发射工作的时间表。

CronTrigger,你可以指定触发的时间表如“每星期五中午”,或“每个工作日9:30时”,甚至“每5分钟一班9:00和10:00逢星期一上午,星期三星期五“。
即便如此,SimpleTrigger一样,CronTrigger拥有的startTime指定的时间表时生效,指定的时间表时,应停止(可选)结束时间。

cron的表达式被用来配置CronTrigger实例。 cron的表达式是字符串,实际上是由七子表达式,描述个别细节的时间表。这些子表达式是分开的空白,代表:

1.        Seconds
2.        Minutes
3.        Hours
4.        Day-of-Month
5.        Month
6.        Day-of-Week
7.        Year (可选字段)
例  "0 0 12 ? * WED" 在每星期三下午12:00 执行,

个别子表达式可以包含范围, 例如,在前面的例子里(“WED”)可以替换成 “MON-FRI”, “MON, WED, FRI”甚至”MON-WED,SAT”.
“*” 代表整个时间段.

每一个字段都有一套可以指定有效值,如

Seconds (秒) :可以用数字0-59 表示,

Minutes(分) :可以用数字0-59 表示,

Hours(时) :可以用数字0-23表示,

Day-of-Month(天) :可以用数字1-31 中的任一一个值,但要注意一些特别的月份

Month(月) :可以用0-11 或用字符串 “JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV and DEC” 表示

Day-of-Week(每周):可以用数字1-7表示(1 = 星期日)或用字符口串“SUN, MON, TUE, WED, THU, FRI and SAT”表示

“/”:为特别单位,表示为“每”如“0/15”表示每隔15分钟执行一次,“0”表示为从“0”分开始, “3/20”表示表示每隔20分钟执行一次,“3”表示从第3分钟开始执行

“?”:表示每月的某一天,或第周的某一天

“L”:用于每月,或每周,表示为每月的最后一天,或每个月的最后星期几如“6L”表示“每月的最后一个星期五”

“W”:表示为最近工作日,如“15W”放在每月(day-of-month)字段上表示为“到本月15日最近的工作日”

““#”:是用来指定“的”每月第n个工作日,例 在每周(day-of-week)这个字段中内容为”6#3” or “FRI#3” 则表示“每月第三个星期五”

接下来就是如何定义个类并且实现Job中的execute方法,如定义一个RefreshTokenJob.java代码如下:

package com.realtech.model;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.context.ApplicationContext;
import  org.springframework.context.support.ClassPathXmlApplicationContext;

import com.realtech.consumer.RefreshTokenConsumer;

/**
 * 定时刷新access_token
 * @author yuanxiaozhong
 * @param jobName jobToken
 * @param groupName groupToken
 * @param cronExpress 
 */
//0 */20 * * * ? 每20分钟执行一次
public class RefreshTokenJob implements Job 

    //token实体类
    private static RefreshTokenConsumer consumer;
    static
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        consumer = (RefreshTokenConsumer) context.getBean("refreshTokenThread");
    

    @Override
    public void execute(JobExecutionContext arg0) throws JobExecutionException 
        consumer.execute();
    


这里使用了spring,我们只需要配置定时任务工厂类即可如:

<!-- 配置定时任务,用于初始化定时器 -->  
<bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">  
</bean>
<!-- 任务管理类 -->
<bean id="scheduleManager" class="com.realtech.model.ScheduleManager">
    <property name="scheduler" ref="schedulerFactoryBean"/>
</bean>
<!-- 定时任务之刷新token -->
<bean id="refreshTokenThread" class="com.realtech.consumer.RefreshTokenConsumer"> 
    <property name="key" value="authorization_access_token"/>
</bean>

在refreshTokenThread中实现具体的任务逻辑,RefreshTokenJob按照指定的重复规则每次都去执行execute方法

最后我们在main方法中完成任务的添加即可:

    package com.realtech.main;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.realtech.model.MessageJob;
import com.realtech.model.RedPacketsLogJob;
import com.realtech.model.RefreshTokenJob;
import com.realtech.model.ScheduleManager;

/**
 * Hello world!
 *
 */
public class App 

    public static void main( String[] args )
    
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        ScheduleManager manager = (ScheduleManager)context.getBean("scheduleManager");
        //添加token刷新任务
        manager.addJob("jobToken", "group3", RefreshTokenJob.class, "0 */20 * * * ?");
        System.out.println("开启任务1");
        manager.startAll();
        System.out.println("启动成功");
    

以上是关于任务调度管理器Quartz漫谈的主要内容,如果未能解决你的问题,请参考以下文章

Quartz运务调度,看完这篇就够了

quartz 定时任务调度管理器

Quartz3.0定时任务学习之异步调度器

定时调度框架quartz可以定义单个触发器多个任务吗

Quartz怎么设置多任务

quartz开源作业调度框架的使用