• Quartz -----定时任务框架


    一.什么是Quartz
     
     
    由java开发用来执行定时任务,类似于java.util.Timer.   但是相较于Timer,quartz增加了很多功能:
            
            持久性作业-就是保持调度定时的状态
     
            作业管理-对调度作业进行有效的管理
     
     
    (1)首先我们需要定义实现一个定时功能的接口,称之为Task(或Job),如定时发送邮件的task(Job),重启机器的task(Job),优惠券到期发送短信提醒的task(Job),实现接口如下:
                         

    (2)有了任务后,还需要一个能够实现触发任务去执行的触发器,触发器Traigger最基本的功能是指定job的执行时间,执行间隔,运行次数等

                   

    (3)有了job和trigger后,怎么样将两者结合起来,即怎样指定Trigger去执行指定的job?这就需要一个schedule,来负责这个功能的实现
          

            

    上面三个部分就是quartz的基本组成部分:
     
                1. 调度器: Scheduler
                2. 任务:    JobDetail
                3. 触发器:Trigger    包括SimpleTrigger和CroTrigger
     
     

    二、Quartz Demo搭建

    下面来利用Quartz搭建一个最基本的Demo。

    1、导入依赖的jar包:

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

    2.配置信息

    # 名为:quartz.properties,放置在classpath下,如果没有此配置则按默认配置启动
    # 指定调度器名称,非实现类
    org.quartz.scheduler.instanceName = DefaultQuartzScheduler04
    # 指定线程池实现类
    org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
    # 线程池线程数量
    org.quartz.threadPool.threadCount = 10 
    # 优先级,默认5
    org.quartz.threadPool.threadPriority = 5
    # 非持久化job
    org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore

    3、新建一个能够打印任意内容的Job:

    public class PrintWordsJob implements Job{
    
        @Override
        public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
            String printTime = new SimpleDateFormat("yy-MM-dd HH-mm-ss").format(new Date());
            System.out.println("PrintWordsJob start at:" + printTime + ", prints: Hello Job-" + new Random().nextInt(100));
    
        }
    }

    4、创建Schedule,执行任务:

    public class MyScheduler {
    
        public static void main(String[] args) throws SchedulerException, InterruptedException {
            // 1、创建调度器Scheduler
            SchedulerFactory schedulerFactory = new StdSchedulerFactory();
            Scheduler scheduler = schedulerFactory.getScheduler();
            // 2、创建JobDetail实例,并与PrintWordsJob类绑定(Job执行内容)
            JobDetail jobDetail = JobBuilder.newJob(PrintWordsJob.class)
                                            .withIdentity("job1", "group1").build();
            // 3、构建Trigger实例,每隔1s执行一次
            Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "triggerGroup1")
                    .startNow()//立即生效
                    .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                    .withIntervalInSeconds(1)//每隔1s执行一次
                    .repeatForever()).build();//一直执行
    
            //4、执行
            scheduler.scheduleJob(jobDetail, trigger);
            System.out.println("--------scheduler start ! ------------");
            scheduler.start();
    
            //睡眠
            TimeUnit.MINUTES.sleep(1);
            scheduler.shutdown();
            System.out.println("--------scheduler shutdown ! ------------");
    
        }
    }

    运行程序,可以看到程序每隔1s会打印出内容,且在一分钟后结束:

    三、Quartz核心详解

    下面就程序中出现的几个参数,看一下Quartz框架中的几个重要参数:

    • Job和JobDetail
    • JobExecutionContext
    • JobDataMap
    • Trigger、SimpleTrigger、CronTrigger
    1,JobDetail用来绑定job,为job实例提供许多属性:
            . name
            . group
            . jobclass
            . jobDataMap
      jobDetail绑定指定的job,每次Scheduler调度执行一个job时,首先会拿到对印的job,然后先创建该job实例,再去执行再去执行job中的execute()的内容,任务执行结束后,关联的job对象实例会被释放,且会被jvm GC清除
     
      jobDetail定义的是任务数据,而真正的执行逻辑实在job中。
      这是应为任务时有可能并发执行的,如果Scheduler直接使用job,就会存在对同一个job实例并发访问的问题, 而JobDetail & Job 方式,Sheduler每次执行,都会根据JobDetail创建一个新的Job实例,这样就可以规避并发访问的问题。

    2.JobExecutionContext
      JobExecutionContext中包含了Quartz运行时的环境以及Job本身的详细数据信息。
    当Schedule调度执行一个Job的时候,就会将JobExecutionContext传递给该Job的execute()中,Job就可以通过JobExecutionContext对象获取信息。

                                   

    3.JobDataMap

      JobDataMap实现了JDK的Map接口,可以以Key-Value的形式存储数据。
      JobDetail、Trigger都可以使用JobDataMap来设置一些参数或信息,
      Job执行execute()方法的时候,JobExecutionContext可以获取到JobExecutionContext中的信息:

    4.Trigger、SimpleTrigger、CronTrigger

        (1).trigger是Quartz的触发器,会去通知Scheduler何时去执行对应job
     
                 new Trigger().startAt():表示触发器首次被触发的时间; 
                 new Trigger().endAt():表示触发器结束触发的时间;
     
     
        (2)  SimpleTrigger:  可以实现在一个时间段内执行一次作业任务或一个时间段内多次执行作业任务。
     
     
        (3) CronTrigger:CroTrigger功能非常强大,是基于日历的作业调度,而SimpleTrigger是精准指定间隔,所以相比SimpleTrigger,CronTrigger更加常用。CroTrigger是基于Cron表达式的,cron表达式格式如下: 
                                  
      [秒] [分] [小时] [日] [月] [周] [年]
     可通过在线生成Cron表达式的工具:http://cron.qqe2.com/ 来生成自己想要的表达式。

     

    下面的代码就实现了每周一到周五上午15:00执行定时任务

    public class MyScheduler2 {
    
        public static void main(String[] args) throws SchedulerException {
            //创建调度器Scheduler
            SchedulerFactory schedulerFactory=new StdSchedulerFactory();
            Scheduler scheduler=schedulerFactory.getScheduler();
            //创建jobDetail实例,并与printWordsJob类绑定(job执行内容)
            JobDetail jobDetail= JobBuilder.newJob(PrintWordsJob.class).usingJobData("jobDetail1","这个job用来测试的")
                    .withIdentity("job1","group1").build();
            //构建Trigger实例,每隔一秒执行一次
            //实现程序运行5s后开始执行Job,执行Job 5s后结束执行:
            Date startDate=new Date();
            startDate.setTime(startDate.getTime()+5000);
            Date endDate=new Date();
            endDate.setTime(startDate.getTime()+5000);
            CronTrigger cronTrigger=TriggerBuilder.newTrigger().withIdentity("trigger1", "triggerGroup1")
                    .usingJobData("trigger1", "这是jobDetail1的trigger")
                    .startNow()
                    .startAt(startDate)
                    .endAt(endDate)
                    .withSchedule(CronScheduleBuilder.cronSchedule("* 00 15 ? * 1/5 2019")).build();
    
            scheduler.scheduleJob(jobDetail,cronTrigger);
            System.out.println("--------scheduler start ! ------------");
            scheduler.start();
            System.out.println("--------scheduler shutdown ! ------------");
    
    
        }
    }

    原文链接:https://blog.csdn.net/noaman_wgs/article/details/80984873

  • 相关阅读:
    AbstractRoutingDataSource动态数据源切换,AOP实现动态数据源切换
    SPEC CPU——简介和使用
    Python——sklearn 中 Logistics Regression 的 coef_ 和 intercept_ 的具体意义
    伯努利分布的最大似然估计(最小化交叉熵、分类问题)
    Python关于%matplotlib inline
    MySQL——告别慢SQL,如何去写一手好SQL
    HiveSQL——row_number() over() 使用
    Python——Python缓存技术
    solr——Lucene打分公式的数学推导
    solr——影响Lucene对文档打分的四种方式
  • 原文地址:https://www.cnblogs.com/rong0912/p/12073488.html
Copyright © 2020-2023  润新知