码迷,mamicode.com
首页 > 其他好文 > 详细

Quartz入门

时间:2019-08-19 00:15:52      阅读:144      评论:0      收藏:0      [点我收藏+]

标签:uart   schedule   tac   esc   任务定义   自己   编程   RKE   www   

一、Quartz介绍

直接看官网吧,Quartz官网

什么是 Quartz Job Scheduling Library?

Quartz是一个功能丰富的开源任务调度库,几乎可以集成在任何Java应用程序中 - 从最小的独立应用程序到最大的电子商务系统。Quartz可用于创建简单或复杂的计划,以执行数十,数百甚至数万个任务; 将任务定义为标准Java组件的任务,这些组件可以执行几乎任何可以编程的程序。Quartz Scheduler包含许多企业级功能,例如支持JTA事务和集群。

下载地址:http://www.quartz-scheduler.org/downloads/

技术图片

官网终最新已经是version:2.4.0的版本了,另外需要提醒的是1.x和2.x的版本差别挺大的,学习和使用主要是使用2.x的版本

我们选择2.4.0的版本进行下载,我们主要是用其Jar包

技术图片

第一个c3p0的依赖,是个数据库连接池,本次案例用不上。

二、Quartz案例

使用idea新建一个普通的java工程即可,做一个简单的案例,这里就是孤单的使用Quartz,没有与Spring做整合。

直接上代码:

package com.helius.job;

import com.helius.service.MeetingService;
import org.quartz.*;

import java.util.List;

/**
 * @Author Helius
 * @Create 2019-08-18-20:48
 */
public class PlanJob implements Job {
    MeetingService meetingService = new MeetingService();

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        TriggerKey triggerKey = jobExecutionContext.getTrigger().getKey();// 这个其实就是TestQuartz类的withIdentity方法中定义的属性
        JobKey jobKey = jobExecutionContext.getJobDetail().getKey();
        System.out.println(triggerKey + "\t" + jobKey);//这句对应控制台输出的group1.meeting trigger   group1.meeting job

        JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap();
        List infos = (List) jobDataMap.get("infos");
        System.out.println(infos);

        // 存放计划执行的任务
        meetingService.calClassMeeting();

    }
}
package com.helius.service;

/** * @Author Helius
 * @Create 2019-08-18-20:46
 */
// 这个为我们具体要执行的任务
public class MeetingService {
    public void calClassMeeting() {
        System.out.println("需要提醒的任务(召开会议.....)");

    }

}
package com.helius.test;

import com.helius.job.PlanJob;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

import java.text.ParseException;
import java.util.Arrays;
import java.util.List;

/**
 * @Author Helius
 * @Create 2019-08-18-20:51
 */
public class TestQuartz {
    public static void main(String[] args) throws SchedulerException, InterruptedException, ParseException {
//        PlanJob
        JobBuilder jobBuilder = JobBuilder.newJob(PlanJob.class);
        // 产生实际使用的Job
        JobDetail jobDetail = jobBuilder.withIdentity("meeting job", "group1").build();

        // 向Job的execute()中传入一些参数
        JobDataMap jobDataMap = jobDetail.getJobDataMap();
        List<String> names = Arrays.asList(new String[]{"zs","ls","ww"});
        jobDataMap.put("infos",names);

        // 下面这几句关于TriggerBuilder可以采用方法链的写法更简洁,因为返回的是当前对象this
        // 触发器:时间规则,,依赖两个对象(TriggerBuilder,Scheduel)
        TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
        triggerBuilder = triggerBuilder.withIdentity("meeting trigger", "group1");
        triggerBuilder.startNow();//当满足条件时执行

/*        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date start = sdf.parse("2019-8-18 21:20:45");
        Date end = sdf.parse("2019-8-18 21:20:55");
        triggerBuilder.startAt(start);
        triggerBuilder.endAt(end);*/

        //ScheduleBuilder:定执行的周期
        SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule();
        scheduleBuilder.withIntervalInSeconds(1);// 每隔一秒执行一次
        scheduleBuilder.withRepeatCount(2);//执行2次
        // 产生触发器
        SimpleTrigger trigger = triggerBuilder.withSchedule(scheduleBuilder).build();



        // 调度器(工厂产生调度器)
        SchedulerFactory schedulerFactory = new  StdSchedulerFactory();
        // 产生调度器
        Scheduler scheduler = schedulerFactory.getScheduler();
        // 产生一个默认的调度器,与上面两句代码等价
        //Scheduler defaultScheduler = StdSchedulerFactory.getDefaultScheduler();
        
        // 通过调度器 将  任务  和 触发器 一一对应
        scheduler.scheduleJob(jobDetail,trigger);
        scheduler.start();

        Thread.sleep(10000); // 休眠10秒,保证关闭前代码任务执行完了
        // 关闭方法
        scheduler.shutdown(); // 如果不shutdown,应用不会停止,因为还有活动的线程
    }
}

打印下结果

group1.meeting trigger  group1.meeting job
[zs, ls, ww]
需要提醒的任务(召开会议.....)
group1.meeting trigger  group1.meeting job
[zs, ls, ww]
需要提醒的任务(召开会议.....)
group1.meeting trigger  group1.meeting job
[zs, ls, ww]
需要提醒的任务(召开会议.....)

就是这么简单,先把代码跑起来,再来具体学习。

先看PlanJob类,实现了Job类,这是Quartz中的类,表示这是一任务,实现这个Job唯一的抽象方法execute,当我们看示例代码时,我们可以只关注meetingService.calClassMeeting();这一句任务的执行代码即可,

方法execute有一个参数:JobExecutionContext jobExecutionContext即Job执行的上下文对象,当然听这个名字,就能知道通过这个对象,我们能拿到很多我们可能在任务执行的时候需要的信息。


考虑这样一个需求,我们的任务是提醒开会,那提醒哪些人需要开会呢,好像在打印的过程中,我们输出了

[zs, ls, ww]

这样一行信息,我们怎么加进去呢,

TestQuartz类中有这样的代码

        // 向Job的execute()中传入一些参数
        JobDataMap jobDataMap = jobDetail.getJobDataMap();
        List<String> names = Arrays.asList(new String[]{"zs","ls","ww"});
        jobDataMap.put("infos",names);

然后我们在PlanJob中可以动态的拿到这些信息

        JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap();
        List infos = (List) jobDataMap.get("infos");
        System.out.println(infos);

其实还有另外一种写法,通过usingJobData这个方法,这里采用了链式写法, 建议自己写一下。

          //定义一个JobDetail
            JobDetail job = newJob(MailJob.class) //指定干活的类MailJob
                .withIdentity("mailjob1", "mailgroup") //定义任务名称和分组
                .usingJobData("email", "admin@10086.com") //定义属性
                .build();

再来看PlanJob类中的

        TriggerKey triggerKey = jobExecutionContext.getTrigger().getKey();
        JobKey jobKey = jobExecutionContext.getJobDetail().getKey();
        System.out.println(triggerKey + "\t" + jobKey);

这个就对印我们输出行中的,毕竟任务可能有很多,所以我们需要给他们分个组,加个id,即加个唯一标志符。

group1.meeting trigger  group1.meeting job

剩下的一些代码,在注释里面已经写的很详细了,不再细讲了

三、Quartz的异步

Quartz有这样一个特性,就是在第一个任务未执行完,第二个任务便会继续开始,我们来测试下,我们改写一下PlanJob类,

public class PlanJob implements Job {
    MeetingService meetingService = new MeetingService();

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        TriggerKey triggerKey = jobExecutionContext.getTrigger().getKey();
        JobKey jobKey = jobExecutionContext.getJobDetail().getKey();
        System.out.println(triggerKey + "\t" + jobKey);

        JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap();
        List infos = (List) jobDataMap.get("infos");
        System.out.println(infos);

        // 存放计划执行的任务
        meetingService.calClassMeeting();
        try {
            Thread.sleep(5000);  // 休眠5秒
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("执行完了");
    }
}

观察控制台:

group1.meeting trigger  group1.meeting job
[zs, ls, ww]
需要提醒的任务(召开会议.....)
group1.meeting trigger  group1.meeting job
[zs, ls, ww]
需要提醒的任务(召开会议.....)
group1.meeting trigger  group1.meeting job
[zs, ls, ww]
需要提醒的任务(召开会议.....)
执行完了
执行完了
执行完了

在第一个任务执行后,中途会有5秒的休眠时间,但是第二个任务依旧开始了

默认的情况下,无论上一次任务是否结束或者完成,只要规定的时间到了,那么下一次就开始。

有时候会做长时间的任务,比如数据库备份,这个时候就希望上一次备份成功结束之后,才开始下一次备份,即便是规定时间到了,也不能开始,因为这样很有可能造成 数据库被锁死 (几个线程同时备份数据库,引发无法预计的混乱)。

那么在这种情况下,给数据库备份任务增加一个注解就好了: @DisallowConcurrentExecution

给PlanJob类加上注解后,

再次运行TestQuartz类,观察控制台输出结果:

group1.meeting trigger  group1.meeting job
[zs, ls, ww]
需要提醒的任务(召开会议.....)
执行完了
group1.meeting trigger  group1.meeting job
[zs, ls, ww]
需要提醒的任务(召开会议.....)
执行完了
group1.meeting trigger  group1.meeting job
[zs, ls, ww]
需要提醒的任务(召开会议.....)
执行完了

和我们预计的一样。
Tips:Quartz的官网的文档很详细,例子也很多,英文也使用的很简单,值得详细阅读。
好像还有很多没讲完,睡觉睡觉,加油加油!!!

Quartz入门

标签:uart   schedule   tac   esc   任务定义   自己   编程   RKE   www   

原文地址:https://www.cnblogs.com/heliusKing/p/11374520.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!