quartz理解

参考:http://blog.csdn.net/evankaka/article/details/45361759
http://www.cnblogs.com/hafiz/p/6159280.html
https://www.ibm.com/developerworks/cn/opensource/os-cn-quartz/

cron表达式:http://www.cnblogs.com/linjiqin/archive/2013/07/08/3178452.html

基本介绍和核心接口

(1)quartz是完全基于java的可用于进行定时任务调度的开源框架,使用的时候需要引入:

<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.2.1</version>
</dependency>

(2)核心接口包括:

  • Job: 就是要执行的任务,该接口只有一个方法execute(JobExecutionContext jobExecutionContext)方法,Job运行时的信息保存在JobDataMap中(JobDataMap下面介绍)
  • JobDetail: 定义Job的实例。接收Job名字、描述以及Job类等信息
  • Trigger: 触发Job运行的东西,主要包括四类:SimpleTriger、CronTrigger、DateIntervalTrigger和NthIncludeDayTrigger,目前常用的是前两种
  • JobBuilder: 定义和创建JobDetail实例的接口
  • TriggerBuilder: 定义和创建Trigger实例的接口
  • Scheduler: quartz的运行容器,Trigger和JobDetail可以注册到scheduler中,两者在Scheduler中拥有各自的组及名称(组及名称是Scheduler查找定位容器中某一对象的依据),Trigger和JobDetail的组合名称都必须唯一,但是两者的组和名称可以相同,因为它们是不同类,一个job可以对应多个trigger,但是一个trigger只能对应一个job

注意:
传递给scheduler的是JobDetail而不是Job,JobDetail通过接收到的有关Job的信息,使用反射机制实例化Job,并且每次Job执行完之后,Job class的实例会被丢弃,Jvm的垃圾回收器会将他们回收.通过这些介绍,所以Job实例实现时,需要注意以下几点:

  • 它必须具有一个无参构造函数
  • 它不应该有静态数据类型。因为每次job实例执行完之后便被回收,而静态成员变量因为依附于类存在,并不能被回收,如果静态变量的值被某个类修改,它的值就没法被保护

这些接口的关系图如下:
这里写图片描述

线程

在Quartz中,有两类线程,Shceduler调度线程和任务执行线程,前者包括普通任务调度和Misfire任务调度(Misfire见这里后者需要一个线程池维护,调度图如下:
这里写图片描述

传递数据

尽管Job类不好定义静态变量,但是可以通过JobDataMap传递数据,JobDataMap是JobDetail的成员变量,可以借助JobDataMap为Job实例提供属性/配置,可以通过它来追踪Job的执行状态等等。对于第一种情况,可以在创建Job时,添加JobDataMap数据,在Job的execute()中获取数据(参见下面simpleTrigger的使用实例)第二种,则可以在Listener中通过获取JobDataMap中存储的状态数据追踪Job的执行状态(这个不是很懂)。

使用实例

1、SimpleTrigger

Job类:

public class SimpleQuartzJob implements Job {

    public SimpleQuartzJob(){}

    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        System.out.println("In SimpleQuartzJob - executinog its JOB at " + new Date() + "by" +
                jobExecutionContext.getMergedJobDataMap().get("testKey") + " " +
                jobExecutionContext.getJobDetail().getJobDataMap().get("testKey") + " " +
                jobExecutionContext.getJobDetail().getKey() + "\n" +
                jobExecutionContext.getJobDetail().toString()
        );
        jobExecutionContext.getMergedJobDataMap().put("state",1);
    }
}

执行测试:

public class SimpleTriggerTest {
    public static void main(String[] args) throws SchedulerException {
        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        //获取scheduler
        Scheduler scheduler = schedulerFactory.getScheduler();

        //定义jobDetail
        JobDetail job = JobBuilder.newJob(SimpleQuartzJob.class).withIdentity("simpleJob", "group2").build();
        job.getJobDataMap().put("testKey", "vava");

        Trigger trigger = TriggerBuilder.newTrigger().withIdentity("tigger1", "group1").startNow()
                .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1)
                        .withRepeatCount(10)).build();

        scheduler.scheduleJob(job, trigger);

        scheduler.start();

    }
}

最后输出:
这里写图片描述

2、CronTrigger

结合Spring使用,首先引入一依赖:

    <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>4.2.6.RELEASE</version>
    </dependency>
    <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>4.2.6.RELEASE</version>
    </dependency>

在这里,配置Job有两种方式:
(1)利用JobDetailBean包装QuartJobBean子类(即Job类)的实例,这种方式可以给作业传递数据
(2)利用MethodInvokiingJobDetailFactoryB工厂Bean包装普通的Java对象(即Job类)

  • 采用第一种方法创建Job类,一定要继承QuartzJobBean,实现executeInternal(JobExecutionContextjobexecutioncontext)方法,此方法就是被调度任务的执行体,然后将此Job类的实例直接配置到JobDetailBean中即可。这种方法和在普通的Quartz编程中是一样的。
  • 采用第二种方法创建Job类,无须继承父类,直接配置MethodInvokingDetailFactoryBean即可,但需要指定一些属性:
    (1)targetObject:指定包含任务执行体的Bean实例。
    (2)targetMethod:指定Bean实例的该方法包装成任务的执行体
    (3)concurrent(可选):是否并发进行,false表示不可以并发

例子:
方式一
job实例:

public class CronQuartzJob extends QuartzJobBean {
    private static final Logger logger = LoggerFactory.getLogger(CronQuartzJob.class);
    private Integer timeout;

    public void setTimeout(Integer timeout){
        this.timeout = timeout;
    }

    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        logger.info("CronTrigger类型任务进行中....");
        System.out.println(timeout);
    }
}

applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean name="secondCron" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
        <property name="jobClass" value="cron.CronQuartzJob"/>
        <property name="jobDataAsMap">
            <map>
                <entry key="timeout" value="90"/>
            </map>
        </property>
    </bean>

    <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
        <property name="jobDetail" ref="secondCron"/>
        <property name="cronExpression" value="0 50 18 * * ?"/>
    </bean>

    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean" id="scheduler">
        <property name="triggers">
            <list>
                <ref bean="cronTrigger"/>
            </list>
        </property>
    </bean>
</beans>

执行测试类:

public class CronTriggerTest {
    public static void main(String[] args) throws SchedulerException {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    }
}

执行结果:
这里写图片描述
可以看到,在配置文件中传入了参数timeout在job中得到了执行

方式二
job实例:

public class CronQuartzJob2 {
    private static final Logger logger = LoggerFactory.getLogger(CronQuartzJob2.class);

    public void executeJob() {
        logger.info("cronQuartzJob 正在运行");
    }
}

配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean name="thirdCron" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject">
            <bean class="cron.CronQuartzJob2"/>
        </property>
        <property name="targetMethod" value="executeJob"/>
        <!--作业不并发调度 -->
        <property name="concurrent" value="false"/>
    </bean>

    <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
        <property name="JobDetail" ref="thirdCron"/>
        <property name="cronExpression" value="0 46 18 * * ?"/>
    </bean>

    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <list>
                <ref bean="cronTrigger"/>
            </list>
        </property>
    </bean>

</beans>

执行结果:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/u014473112/article/details/80525250
今日推荐