• Quartz-第一篇 认识Quartz


    1、什么是Quartz

       Quartz是一个任务调度框架,借助Cron表达式,Quartz可以支持各种复杂的任务调度。JDK中也提供了简单的任务调度,java.util.Timer。

       Quartz的三大要素:作业bean(JobDetailBean)、触发器(Trigger)、调度器(Scheduler)

    2、Quartz运行的基本属性

       quartz有一个默认的配置文件quartz.properties,放置于quartz-2.2.2.jar中的orgquartz下。如果需要改变默认的配置,可以自己创建一个,将其放置于系统的类加载路径下,ClassLoader会自动加载并启动其中的属性。

       

       查看其中内容:

    # 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
    #配置线程池
    #quartz线程池的实现类 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.class: org.quartz.simpl.RAMJobStore

       quartz提供了两种作业存储方式:

          1》RaMJobStore:利用内存来持久化调度程序信息。这种作业存储类型易于配置和运行,但程序退出后配置信息也就丢失了。

          2》JDBC作业存储:JDBC驱动程序+后台数据库保存调度程序信息。

    3、quartz中的Job

       Job是一个执行指定任务的java类,当quartz调用某个java任务执行时,实际上就是执行该任务对象的execute()方法。quartz中的作业需要实现org.quartz.Job接口,该接口中包含一个execute()方法,该方法的方法体是被调度的作业体。

       一旦实现了Job接口和execute()方法,当quartz调度该作业运行时,该execute()方法就会自动运行起来。

      使用JobDetail包装一个作业,在包装时,包括给作业指定作业名,指定作业所在的组。

    4、quartz中的触发器

       quartz允许作业与作业调度分离,使用触发器将作业与作业调度分离。触发器指定任务的被调度时机,其框架提供了一系列触发器类型,常用的有:

       1》SimpleTrigger:简单触发器。

       2》CronTrigger:用于执行更复杂的调度,基于Unix Cron。该调度器基于Calendar-like。

            Cron表达式是一个字符串,字符串以5个或6个空格隔开,分成6个或7个域,每个域代表一个时间域。Cron表达式有两种语法格式。

    5、quartz中的调度器

        调度器用于将任务和触发器关联起来,一个任务可以关联多个触发器,一个触发器也可以用于控制多个任务。当一个任务关联多个触发器时,每个触发器被激活时,这个任务都会被调度一次;当一个触发器控制多个任务时,此触发器被触发时,所有关联的任务都将被调度。

        quartz的调度器由Scheduler接口实现,其中声明的方法有:

           1》void addJob(JobDetail jobDetail,boolean replace):将给定的JobDetail实例添加到调度器里。

           2》Date scheduleJob(JobDetail jobDetail,Trigger trigger):将指定的JobDetail实例与给定的triger关联起来,即使用该trigger来控制该任务。

           3》Date scheduleJob(Trigger trigger):添加触发器trigger来调度作业。

    6、spring中整合quartz

       spring的任务的任务调度抽象层简化了任务调度,在quartz基础上提供了更好的调度抽象。创建quartz作业bean(即:JobDetailBean)有以下两个方法:

          1》使用JobDetailBean包装QuartzJobBean子类的实例。即作业bean必须继承于QuartzJobBean类,它是一个抽象类,包含的方法有:

               1>executeInternal(JobExecutionContext ctx):被调度任务的执行体

          2》使用MethodInvokingJobDetailFactoryBean工厂bean包装普通的Java bean

               使用MethodInvokingJobDetailFactoryBean包装,则无需继承任何父类,直接使用配置即可,配置MethodInvokingJobDetailFactoryBean,需要指定以下两个属性:

               1>targetObject:指定包含任务执行体的bean实例。

               2>targetMethod:指定将指定bean实例的该方法包装成任务执行体。

          3》应用步骤举例:

               --步骤1:创建JobDetailBean

              1>使用JobDetailBean(或者JobDetailFactoryBean)包装作业bean的配置举例

    <!--定义JobDetailBean bean-->
    <!--以指定QuartzJobBean子类实例的executeInternal()方法作为任务实体-->
    <bean name="quartzDetail" class="org.springframework.scheduling.quartz.JobDetailBean" p: jobClass="QuartzJobBean子类"/>

               2>使用MethodInvokingJobDetailFactoryBean包装

    <!--定义目标bean-->
    <bean id="mailQuartz" class="com.lfy.bean.MailQuartz"/>
    <!--定义MethodInvokingJobDetailFactoryBean bean-->
    <bean id="quartzDetail"
          class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"
          p:targetObject-ref="mailQuartz" 
          p:targetMethod="send"/>

        完成以上两种不同的JobDetailBean作业bean注册后,只需以下两个步骤即可完成任务的调度:

           1>使用SimpleTriggerBean或CronTriggerBean定义触发器Bean。    --步骤2:创建触发器

           2>使用SchdulerFactoryBean调度作业。                                        --步骤3:创建调度器

     7、举个简单的例子

       

       编写JobDetailBean:GreetJob.java

    package com.lfy.jobdetailbean;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    import org.quartz.JobExecutionContext;
    import org.quartz.JobExecutionException;
    import org.springframework.scheduling.quartz.QuartzJobBean;
    
    import com.lfy.bean.Tomcat;
    
    public class GreetJob extends QuartzJobBean{
    
        //作业是否正在执行的flag
        private boolean isRunning=false;
        private String name;
        private Tomcat tomcat;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
        
        public Tomcat getTomcat() {
            return tomcat;
        }
    
        public void setTomcat(Tomcat tomcat) {
            this.tomcat = tomcat;
        }
        
        public void sayHello() {
            System.out.println(name+",你好呀。");
        }
        
        private String getTimeStamp(long timestamp) {
            
            Date date=new Date(timestamp);
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String timeStamp=dateFormat.format(date);
            return timeStamp;
        }
    
        @Override
        protected void executeInternal(JobExecutionContext ctx) throws JobExecutionException {
            
            long currentTime=System.currentTimeMillis();
            String timeStamp=getTimeStamp(currentTime);
            System.out.println(timeStamp+":executeInternal()有调度线程进来...");
            if(!isRunning) {
                System.out.println("开始调度作业...");
                isRunning=true;
                sayHello();
                tomcat.selfIntroduction(name);
                isRunning=false;
            }
            currentTime=System.currentTimeMillis();
            timeStamp=getTimeStamp(currentTime);
            System.out.println(timeStamp+":executeInternal()线程从函数返回...
    ");
        }
    }

        Tomcat.java

    package com.lfy.bean;
    
    public class Tomcat {
    
        public void selfIntroduction(String name) {
            
            System.out.println("hello,我是"+name+"家的汤姆猫。");
        }
    }

        在beans.xml中注册触发器、调度器

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- spring配置文件的根元素,使用spring-beans-4.0.xsd语义约束 -->
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns="http://www.springframework.org/schema/beans" 
           xmlns:p="http://www.springframework.org/schema/p"
           xsi:schemaLocation="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
           
          <bean id="tomcat" class="com.lfy.bean.Tomcat"/>
    <!-- cronExpression表达式指定Cron表达式:从启动开始,每5秒运行一次 --> <bean id="cronTriggerSayHello" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean" p:cronExpression="/5 * * * * ? *"> <property name="jobDetail"> <!-- 使用嵌套bean的方式来定义任务bean,jobClass指定任务bean的实现类 --> <bean class="org.springframework.scheduling.quartz.JobDetailFactoryBean" p:jobClass="com.lfy.jobdetailbean.GreetJob" p:durability="true"> <!-- 为任务bean注入属性 --> <property name="jobDataAsMap"> <map> <entry key="name" value="lfy"/> <entry key="tomcat" value-ref="tomcat"/> </map> </property> </bean> </property> </bean>
    <!-- 执行任务调度 --> <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="cronTriggerSayHello"/> </list> </property> </bean> </beans>

        或者使用另外一种包装job的形式:

    <bean id="generalJob" class="com.lfy.jobdetailbean.GeneralJob"/>
    ...
    <bean id="cronTriggerSayGoodBye" 
                class="org.springframework.scheduling.quartz.CronTriggerFactoryBean" 
                p:cronExpression="/6 * * * * ? *">
                <property name="jobDetail">
                   <bean  class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"
                          p:targetObject-ref="generalJob" 
                          p:targetMethod="greet">
                   </bean>
                </property>
          </bean>
    ...
    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
             <property name="triggers">
                <list>
                   ...
                   <ref bean="cronTriggerSayGoodBye"/>
                </list>
             </property>
          </bean>

        QuartzTest.java

    package com.lfy.main;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class QuartzTest {
    
        public static void main(String[] args) {
            //创建spring容器
            ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
        }
    }

       运行结果:

      总结:

        1》定义一个JobDetailBean,继承自org.springframework.scheduling.quartz.QuartzJobBean,并实现唯一抽象方法executeInternal(),该方法在job被触发的时候自动调用。

        2》将触发器和JobDetailBean关联起来。JobDetailBean作为触发器的属性。

        3》在org.springframework.scheduling.quartz.SchedulerFactoryBean调度工厂中注册触发器。

  • 相关阅读:
    获取指定路径下的文件夹及文件名称
    Unity3D两种方式实现游戏视频播放
    Unity Steam_VR Camera
    Unity Steam_VR 开发工具插件 VRTK自带案例分析(第一部分)
    Unity Steam_VR 开发工具插件 VRTK自带案例分析(第二部分)
    weblogic安装注意事项_linux
    从英文变形规则计算到Restful Api设计
    如何正确使用Cocoapods
    clang -rewrite-objc的使用点滴
    kubernetes听云实战发布版
  • 原文地址:https://www.cnblogs.com/ZeroMZ/p/11356715.html
Copyright © 2020-2023  润新知