quartz学习使用心得(1)

时间:2021-07-21 16:43:37

quartz是一种任务调度框架。

quartz调度的核心元素以及在于spring整合时的存在形式:

!!!核心元素比较多,都是概念性的东西,建议大家一定仔细看,第一遍看不懂没关系,浏览一遍后,结合自己写的demo回过头来细细地看就会清晰很多。)

1、Job:是一个接口,只有一个方法void execute(JobExecutionContext context),开发者在实现该接口的execute方法中编写所需要的定时任务,JobExecutionContext类提供了调度上下文的各种信息。Job运行时的信息保存在JobDataMap实例中。实现接口的任务,默认是无状态的,若要将Job设置成有状态的,在quartz中是给实现的Job添加@DisallowConcurrentExecution注解(以前是实现StatefulJob接口,现在已被Deprecated)。在与spring结合中可以在spring配置文件的jobDetail中配置concurrent参数。

2、JobDetail:用来描述Job实现类及其他相关的静态信息,如Job名字、描述、关联监听器等信息。Quartz每次调度Job时,都创建一个Job实例,所以它不直接接收一个Job实例,相反它接收一个Job实现类。在spring中有JobDetailFactoryBean和MethodInvokingJobDetailFactoryBean两种实现,如果任务调度只需要执行某个类的某个方法,就可以通过MethodInvokingJobDetailFactoryBean来调用。

3、Trigger:触发器,是一个类,描述触发Job执行的时间触发规则。(即用于定义任务调度的时间规则),有SimpleTrigger、CronTrigger、DateIntervalTrigger和NthIncludeDayTrigger,前两个是主要的,其中CronTrigger用的比较多。当且仅当需调度一次或者以固定时间间隔周期执行调度,SimpleTrigger是最适合的选择;而CronTrigger则可以通过Cron表达式定义出各种复杂的时间规则的调度方案。在spring中封装在CronTriggerFactoryBean中。(注:Cron表达式专门开了一片文章,点击此处跳转

4、Calendar:它是一些日历特定时间点的集合。他与java.util.Calendar不同,util那个代表一个日历的时间点,可以简单地将quartz那个看做util那个的集合。一个trigger可以包含多个Calendar,以便排除或包含某些时间点。

假设,我们安排每周一早上10:00执行任务,但是如果碰到法定的节日则不执行任务,这些就需要在Trigger触发机制的基础上使用Calendar进行定点排除。针对不同时间段类型,Quartz在org.quartz.impl.calendar包下提供了若干个Calendar的实现类,如AnnualCalendar、MonthlyCalendar、WeeklyCalendar分别针对每年、每月和每周进行定义。

5、Scheduler:任务调度器,实际执行任务的控制器,代表一个Quartz的独立运行容器,Trigger和JobDetail可以注册到Scheduler中,两者在Scheduler中拥有各自的组及名称,组及名称是Scheduler查找定位容器中的某一对象依据,Trigger的组及名称必须唯一,JobDetail的组及名称也必须唯一(但可以和Trigger的组和名称相同,因为他们不同类型的)。Scheduler定义了多个接口方法,允许外部通过组及名称访问和控制容器中Trigger和JobDetail。在spring中通过SchedulerFactoryBean封装起来。

Scheduler可以被Trigger绑定到某一个JobDetail中,这样当Trigger触发时,对应的Job就被执行。一个Job可以对应多个Trigger,但一个Trigger只能对应一个Job。可以通过SchedulerFactory创建一个Scheduler实例。Scheduler拥有一个SchedulerContext,他类似于ServletContext,保存着Scheduler上下文信息,Job和Trigger都可以访问SchedulerContext内的信息。SchedulerContext内部通过一个Map,以键值对的方式维护这些上下文数据,SchedulerContext为保存和获取数据提供了多个put()和geiXxx()的方法。可以通过Scheduler#getContext()获取对应的SchedulerContext实例。

6、ThreadPool


demo:

/**  * @description 任务调度测试任务  * @author: gaobh  * @date: 2018/3/21 15:58  * @version: v1.0  */ public class HelloQuartz implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        JobDetail detail = context.getJobDetail();
        String name = detail.getJobDataMap().getString("name");
        System.out.println("say hello to " + name + " at " + new Date());
    }
}

上面这段代码就是一个Job的实现类,需要调度的任务。

public static void main(String[] args) {
    try {
        //创建scheduler:调度器。所有的调度都是由他控制
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        //定义一个Trigger 触发的条件
        Trigger trigger = newTrigger().withIdentity("trigger1", "group1")
                //一旦加入scheduler,立即生效
                .startNow()
                //使用SimpleTrigger
                .withSchedule(simpleSchedule()
                        //每隔一秒执行一次
                        .withIntervalInSeconds(2)
                        //一直执行,奔腾到老不停歇
                        .repeatForever())
                .build();

        //定义一个JobDetail
        //定义Job类为HelloQuartz类,这是真正的执行逻辑所在
        JobDetail job = newJob(HelloQuartz.class)
                //定义name/group
                .withIdentity("job1", "group1")
                //定义属性
                .usingJobData("name", "quartz")
                .build();

        //加入这个调度
        scheduler.scheduleJob(job, trigger);
        //启动
        scheduler.start();
        //运行一段时间后关闭
        Thread.sleep(10000);
        scheduler.shutdown(true);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

上面一段代码可以结合之前的quartz的几个核心元素结合着看,会清晰很多:

  • 首先,创建一个调度器Scheduler,所有的调度都是由他来控制

Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
  • 定义一个Trigger触发器,将一些触发条件及基础信息(即组和名称)设置进来,如上的解释,此处就不做说明了,详细的说明结合第一块核心元素的讲解。
  • 定义一个Job类为HelloQuartz.class。
  • 最后,就是将之前准备的一些东西注册到调度器中,并启动。

scheduler.scheduleJob(job, trigger);
scheduler.start();

运行结果:任务每隔两秒调度一次,10秒后停止。

quartz学习使用心得(1)

参考文章:

Quartz入门详解

quartz从原理到应用(详解篇)

这里主要讲解的只是一个简单的实例,我还写了很多其他quartz的学习博客。

Quartz中的Cron表达式

quartz学习使用心得(2)之quartz.properties

quartz学习使用心得(3)之spring与Quartz的整合

quartz定时任务service注入失败