• 最牛逼的任务调度工具 | Quartz


    Quartz 是一个完全由 Java 编写的开源作业调度框架,不要让作业调度这个术语吓着你,其实不难。尽管 Quartz 框架整合了许多额外功能,但就我们使用来说,你会发现它易用得简直让人受不了!

    简单来说,任务调度就是在指定时间做指定的事,之前说过在执行定时定频率作业时可以使用原生 JDK,Timer 和 TimerTask 。

    但是假如我们有一些非常苛刻的要求该怎么办呢?比如,在每年 5 月的第二个星期日和每年 6 月的第三个星期日给我发一个邮件。

    这种看似随机但还有有一点规律的定时任务该怎么实现呢?别急,Quartz 都能给你搞定!

    我们执行任务必须的几个条件,一个是调度器,二是执行的任务,三是触发器(可以理解为设置闹钟)。连在一起就是我们使用调度器将任务和触发器绑定在一起执行,以达到在指定的时间点执行或循环执行任务。

    虽说 Quartz 框架有十多个包,300 多个类,但是我们使用它还是比较容易的。

    首先,创建一个任务,一样的套路我们只需要实现 Job 类,实现特定的方法即可,任务创建成功。

    public class HelloJob implements Job{
        @Override
        public void execute(JobExecutionContext context) throws JobExecutionException {
            TimeUtil.printCurrentTime();
            System.out.println("Hello world!");
        }
    }

    但是我们调度器绑定的不是 Job 的实现类 HelloJob,而是一个 JobDetail,为什么需要它呢,都写在脸上了,Job 详情嘛!

    我们执行任务需要知道任务的名称啊,分组之类的,这样打出来的 log 也好分辨。这个 JobDetail 是和哪个 Job 绑定的呢?我们还要知道 Class 信息。在任务执行的时候可能还需要传参,这些都会封装在 JobDetail 中。

    JobDetail 的创建就更是巧妙了,Quartz 为任务和触发器的创建提供了一种构建器风格的 API。具体的创建就是这样(一路点下去)

    JobDetail jobDetail = JobBuilder.newJob(HelloJob.class).withIdentity("job1", "group1").build();

    呃呃,构建器风格…… 我也不是很懂,感觉用起来很方便就对了,这样我们就创建了一个 JobDetail ,并设置了绑定的 Job (HelloJob),还为任务命名并分组,其实还可以继续绑定参数。这里没有演示而已。

    同样的创建风格也用在触发器身上,想想看我们要设置一个闹钟,我们要设置开始执行的时间,执行的频率,执行的次数,这些一次性搞定,若是你英文还可以,看这些方法应该都明白了。

    Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group").startNow()
                    .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2).repeatForever()).build();

    哎,不是说好了不按套路出牌的嘛,我要的是每年 5 月的第二个星期日执行呀,可不是定时定频率啊,别急,后面说。

    最后,再创建一个调度器,使用工厂模式创建,这里选择 StdSchedulerFactory ,因为这个工厂是可以加载配置文件的。在框架中会默认给我们提供一套配置,我们也可以在项目根目录下自行创建。

    调度器的创建、绑定任务和触发器到执行,几行代码搞定。

    // 定义一个 Schedule,用于绑定任务和触发器
    SchedulerFactory sf = new StdSchedulerFactory();
    Scheduler scheduler = sf.getScheduler();
    scheduler.scheduleJob(jobDetail, trigger);
    scheduler.start();

    好了,这里为此,我们就已经搞定了最牛逼的定时任务的 demo 了。但是,你有没有发现,若是想实现定时定频率的执行任务,使用 Timer 就可以啊,为什么要劳烦大哥出场呢?

    这里提一下 Timer 和 Quartz 的区别吧。

    1、Timer 只能执行定时定频率的任务,而 Quartz 不是。

    2、Timer 只有一个线程在执行,而 Quartz 有线程池,默认开启 10 个线程。

    3、Timer 中出现异常,一切 GG,不能记录事故现场,而 Quartz 可以。

    Quartz 想灵活的设置执行时间,依赖谁呢?调度器?NO,那肯定是触发器啊,其实 Trigger 有两个实现类,一个是 SimpleTrigger 就是功能比较简单的那个,默认实现的就是这个,所以上面我们返回就是 SimpleTrigger 的对象。

    而另一个重磅级的实现类就是 CronTrigger ,它的触发机制是基于日历的,所以,你能想到的每一天,都能给你表示出来,触发器,重点就在这个时间的表示上面,我们使用 Cron 表达式来表示执行的时间。

    举个例子吧 "* * * * * ? *" 表示每秒钟都执行,"0 15 10 ? 6L 2018-2020" 表示 2018-2020 年的每个月的最后一个星期五上午 10:15 执行。你会想,WTF ? 这是什么鬼,我不打算细说这个 Cron 表达式怎么写,因为不需要自己写!简单说,这就类似与正则表达式,而我们可以用在线生成工具来生成他们。

    你只需要搜索 Cron 表达式在线生成器即可。

    有了随心所欲的时间之后,我们就可以使用 CronTrigger 来定义触发器了,核心就在 Cron 表达式上面。

    CronTrigger cronTrigger = (CronTrigger)TriggerBuilder.newTrigger().withIdentity("trigger1", "group").startNow()
                    .withSchedule(CronScheduleBuilder.cronSchedule("* * * * * ? *")).build();       
    

    至于多线程和持久化相关的类都在调度器中,不得不说 Quartz 封装的就是好呀,使用者根本感觉不到这些,在 StdSchedulerFactory 的内部,封装了核心调度器 QuartzScheduler ,用于持久化任务的 JobStore ,多线程相关的线程池、线程执行器。

    但是我这种没有具体业务需求的人是不会深入研究的,对了,不要忘了 Quartz 的可配置的特性,简直就是逆天,没有业务场景应用的我也就想想得了。

    以上也就是带你了解一下 Quartz,自己玩玩完全没问题。但是,你要是还不知道 Timer ,那就是你的问题了,可以回头看看这篇。

    Java 中的定时任务 | 初级

  • 相关阅读:
    谨以此文纪念一周的心血历程
    面向对象初调用:foolish 电梯
    洛谷 1016 旅行家的预算
    洛谷 1514 引水入城
    洛谷 3178 树上操作
    洛谷 3811 【模板】乘法逆元
    洛谷 1156 垃圾陷阱
    洛谷 1363 幻想迷宫
    洛谷 1736 创意吃鱼法
    洛谷 1436 棋盘分割
  • 原文地址:https://www.cnblogs.com/YJK923/p/10199174.html
Copyright © 2020-2023  润新知