zoukankan      html  css  js  c++  java
  • Quartz定时任务调度机制解析(CronTirgger、SimpleTrigger )

    一、Quartz的介绍

      Quartz 是 OpenSymphony 开源组织在任务调度领域的一个开源项目,完全基于 Java 实现。该项目于 2009 年被 Terracotta 收购,目前是 Terracotta 旗下的一个项目。它是一个而安全有java辨析额的开源作业调度框架。

    二、Quartz 具有以下特点

    1.强大的调度功能,例如支持丰富多样的调度方法,可以满足各种常规及特殊需求;

    2.灵活的应用方式,例如支持任务和调度的多种组合方式,支持调度数据的多种存储方式;

    3.分布式和集群能力,Terracotta 收购后在原来功能基础上作了进一步提升;

    4.另外,作为 Spring 默认的调度框架,Quartz 很容易与 Spring 集成实现灵活可配置的调度功能。

    开发企业级任务调度应用Quartz 就是启动定时任务的框架 !! !

    三、基本开发流程及简单实例

      利用 Quartz 进行开发相当简单,只需要将下载开发包中的 quartz-all-1.8.4.jar 加入到 classpath 即可。根据笔者的经验,对于任务调度功能比较复杂的企业级应用来说,最好在开发阶段将 Quartz 的源代码导入到开发环境中来。一方面可以通过阅读源码了解 Quartz 的实现机理,另一方面可以通过扩展或修改 Quartz 的一些类来实现某些 Quartz 尚不提供的功能。

    1.Quartz定时调度框架使用说明

    1) Job任务

      具体要执行任务的程序。比如发短信,发邮件,访问数据库,同步数据,数据的清洗,本项目中使用在宣传活动定时过期的模块。

    2)Trigger触发器 

      a)作用:它是来执行工作任务,在什么条件下触发,什么时间执行,多久执行一次。

      b)四大类型:SimpleTrigger,CronTirgger,DateIntervalTrigger, 和 NthIncludedDayTrigger。

      SimpleTrigger 一般用于实现每隔一定时间执行任务,以及重复多少次,如每 2 小时执行一次,重复执行 5 次。SimpleTrigger 内部实现机制是通过计算间隔时间来计算下次的执行时间,这就导致其不适合调度定时的任务。例如我们想每天的 1:00AM 执行任务,如果使用 SimpleTrigger 的话间隔时间就是一天。注意这里就会有一个问题,即当有 misfired 的任务并且恢复执行时,该执行时间是随机的(取决于何时执行 misfired 的任务,例如某天的 3:00PM)。这会导致之后每天的执行时间都会变成 3:00PM,而不是我们原来期望的 1:00AM。

      CronTirgger 类似于 LINUX 上的任务调度命令 crontab,即利用一个包含 7 个字段的表达式来表示时间调度方式。例如,"0 15 10 * * ? *" 表示每天的 10:15AM 执行任务。对于涉及到星期和月份的调度,CronTirgger 是最适合的,甚至某些情况下是唯一选择。例如,"0 10 14 ? 3 WED" 表示三月份的每个星期三的下午 14:10PM 执行任务。读者可以在具体用到该 trigger 时再详细了解每个字段的含义。

    3)scheduler定时器
    Scheduler就是用来启动Trigger去执行Job。

      在 Quartz 中, Scheduler 由 scheduler 工厂创建:DirectSchedulerFactory 或者 StdSchedulerFactory。 第二种工厂 StdSchedulerFactory 使用较多,因为 DirectSchedulerFactory 使用起来不够方便,需要作许多详细的手工编码设置。 Scheduler 主要有三种:RemoteMBeanScheduler, RemoteScheduler 和 StdScheduler。

    2.简单案例

    【使用步骤】:
    1.导入quartz和quartz-job 的jar包
    2.定义job任务类,该任务类需要实现接口Job,并重写方法
    3.创建定时器对象
    StdSchedulerFactory.getDefaultSchedule()获得的是一个定时器Scheduler对象

    4.创建一个工作(jobDetail)对象实例,设置它的名字、组(当trigger去触发job的时候,是按照名字和分组去进行触发的)
    a.JobBuilder.newJob(HelloJob.class) //创建builder,(jobDetail的预准备对象)
    b.通过builder调用withIdentity()去设置builder的名字和分组
    c.最后通过build()方法获得一个jobDetail对象

    5.定义一个触发器trigger对象,用来执行jobDetail
    a.TriggerBuilder.newTrigger() //创建一个触发器trigger对象,

    b.withIdentity(“trigger_1”, “group_1”) //设置触发器的名字和分组

    c.startNow() //设置触发器开始执行JobDetail的起始时间,还有startAt() 在指定的时间去执行

    //设置以哪种方式执行JobDetail
    [有两种方式]
    一种是:SimpleScheduleBuilder 简单任务的重复执行
    另一种是:CronTrigger 按日历触发任务
    //以及执行一次JobDetail的间隔时间,以及执行到什么时候
    d.withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(5))

    e.build() 最终获得一个Trigger对象

    6.开启定时任务
    scheduler.start();

    【CronTrigger 按日历触发任务 简介】
             [Cron表达式]:
                 由7个子表达式组成的字符串,每个子表达式都描述了一个单独的日程细节,这些子表达式用空格分割,分别表示:
                 1.Seconds      秒
                 2.Minutes         分
                 3.Hours        小时
                 4.Day-of-Month 月中的天,可选值(1-315.Month        哪一个月,可选值(JAN、FEB、MAR、APR、MAY、JUN、JUL、AUG、SEP、OCT、NOV、DEC)
                 6.Day-of-Week  周中的天,可选值(SUN、MON、TUE、WED、THU、FRI、SAT)    
                 7.Year            年(可选的域,可有可无)
    
            [特殊字符]
                '/'  用来表示增量
                '?'  用来表示没有执行的值,但是,4、6不能同时使用'?' 它们必须指定一项 否则会报错
                '*'  通配符,表示所有可能的值
            [Cron表达式示例]:
                0 0 12 ? * WED     -------表示每周三的中午12:00
    
                0/15如果放在第一位,表示从0开始,每15分钟执行一次

    【使用案例一】:

    【使用案例1】:
            [创建job类,使用SimpleSchedulerBuilder]:
            
                import org.quartz.Job;
                import org.quartz.JobExecutionContext;
                import org.quartz.JobExecutionException;
    
                //quartz的任务
                public class HelloJob implements Job {
                    public static int i = 0;
                    public void execute(JobExecutionContext context) throws JobExecutionException {
                        System.out.println("hello quartz............"+(i++));
                    }
                }
    
            [测试类]:
                import org.junit.Test;
                import org.quartz.JobBuilder;
                import org.quartz.JobDetail;
                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;
    
                import job.HelloJob;
    
                //在测试的时候遇到一个问题,如果使用JUnit来进行测试的话,进程会死掉
                public class HelloScheduler {
                    public static void main(String[] args) throws SchedulerException {
                        //创建一个定时器对象
                        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
                        
                        //定义一个工作对象
                        JobDetail jobDetail = JobBuilder.newJob(HelloJob.class).withIdentity("job_1","group1").build();
                        
                        //定义触发器
                        Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger_1", "group_1")
                                    .startNow().withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(5)).build();
                        
                        scheduler.scheduleJob(jobDetail, trigger);
                        
                        //开启定时任务
                        scheduler.start();
                    }
                }

    【使用案例二】:

    【使用案例2】:
            [创建job类,使用CronSchedulerBuilder]:
                import org.quartz.Job;
                import org.quartz.JobExecutionContext;
                import org.quartz.JobExecutionException;
    
                public class SecondJob implements Job{
    
                    public void execute(JobExecutionContext context) throws JobExecutionException {
                        System.out.println("使用crontrigger....");
                    }
    
                }
    
    
            [创建测试类]:
                import org.quartz.CronScheduleBuilder;
                import org.quartz.JobBuilder;
                import org.quartz.JobDetail;
                import org.quartz.Scheduler;
                import org.quartz.Trigger;
                import org.quartz.TriggerBuilder;
                import org.quartz.impl.StdSchedulerFactory;
    
                import job.SecondJob;
    
                public class SecondScheduler {
                    public static void main(String[] args) throws Exception {
                        //创建一个定时器对象
                        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
                        
                        //创建一个jobDetail对象
                        JobDetail jobDetail = JobBuilder.newJob(SecondJob.class).withIdentity("job_2", "group_2").build();
                        
                        //创建一trigger
                        Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger_2", "group_2")
                                .startNow().withSchedule(CronScheduleBuilder.cronSchedule("0 17 1 * * ?")).build();
                        
                        scheduler.scheduleJob(jobDetail,trigger);
                        scheduler.start();
                    }
                }

    通过以上案例,可以了解到quart的使用和简单入门操作。

      当然,作为当前颇具生命力的开源框架,Quartz 已经得到了广泛的应用。Quartz 的强大功能和应用灵活性,在企业应用中发挥了巨大的作用。本文描述了如何应用 Quartz 开发应用程序,并对企业应用中常见的问题及解决方案进行了讨论。

  • 相关阅读:
    missing requires of libmysqlclient.so.18()(64bit)
    Ambari安装HDP问题:User root is not allowed to impersonate anonymous.User: hcat is not allowed to impersonate ambari-qa
    ambari2.6.50 openssl 版本问题:SSLError: Failed to connect. Please check openssl library versions. Openssl error upon host registration
    HDP 2.6 requires libtirpc-devel
    Kafka 如何读取offset topic内容 (__consumer_offsets)
    Linux集群时间同步方法
    centos7 ambari2.6.1.5+hdp2.6.4.0 大数据集群安装部署
    Centos7.3离线(rpm方式)安装mysql服务
    ubuntu安装rpm的方法
    kerberos环境storm配置:Running Apache Storm Securely
  • 原文地址:https://www.cnblogs.com/blogslee/p/6910763.html
Copyright © 2011-2022 走看看