0%

Quartz原理与实战

定时任务与基本概念

在指定的时间,做指定的动作

简单启动一个调度器

public class QuartzTest {
    public static void main(String[] args) {

        try {
            //从调度器工程获得一个调度器
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

            // 启动
            scheduler.start();

            scheduler.shutdown();

        } catch (SchedulerException se) {
            se.printStackTrace();
        }
    }
}

示例代码,获取scheduler实例对象,启动,然后关闭。
当调用StdSchedulerFactory.getDefaultScheduler()获取scheduler实例对象后,在调用scheduler.shutdown()之前,scheduler不会终止,因为还有活跃的线程在执行。


日期格式类,用于转变格式

import java.text.SimpleDateFormat;
import java.util.Date;

public class DFUtil {
    public static final SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    public static String format(Date date){
        return sdf.format(date);
    }
}

新建一个HelloJob类

public class HelloJob implements Job {

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        System.out.println("HelloJob.execute"+ DFUtil.format(new Date())+' '+Thread.currentThread().getName());
    }
}

测试实例

在调用shutdown()之前,需要给job的触发和执行预留一些时间,比如,你可以调用Thread.sleep(60000)让线程睡眠一段时间。
定义一个JobDetail和一个Trigger容器,5秒执行一次,永远执行

public static void main(String[] args) {

    try {
        //从调度器工程获得一个调度器
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

        // 启动
        scheduler.start();

        // 定义一个作业详情
        JobDetail job= JobBuilder.newJob(HelloJob.class)
                .withIdentity("job1", "group1")
                .build();

        //触发器定义调度策略
        Trigger trigger= TriggerBuilder.newTrigger()
                .withIdentity("trigger1", "group1")
                .startNow()
                .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                        .withIntervalInSeconds(5)
                        .repeatForever())
                .build();

        // Tell quartz to schedule the job using our trigger
        scheduler.scheduleJob(job, trigger);

        TimeUnit.SECONDS.sleep(20);

        scheduler.shutdown();

    } catch (SchedulerException se) {
        se.printStackTrace();
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
}

执行结果


触发器

一个调度器调度多个触发器,一个触发器只能调度一个任务,一个任务可以被多个触发器调度。

两个触发器调用同一个作业

一般一个任务详情关联一个任务job

SimpleTrigger

实例代码

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

           // Trigger the job to run now, and then repeat every 40 seconds
           Trigger trigger= TriggerBuilder.newTrigger()
                   .withIdentity("trigger1", "group1")
                   .startNow()
                   .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                           .withIntervalInSeconds(1)
                           .repeatForever())
                   .build();

           Trigger trigger2 = TriggerBuilder.newTrigger()
                   .withIdentity("trigger2", "group1")
                   .forJob("job1", "group1")
                   .startNow()
                   .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                           .withIntervalInSeconds(3)
                           .repeatForever())
                   .build();

           // Tell quartz to schedule the job using our trigger
           scheduler.scheduleJob(job, trigger);
           scheduler.scheduleJob(trigger2);

           TimeUnit.SECONDS.sleep(3);

           scheduler.shutdown();

触发器分为四种:
SimpleTrigger
CronTrigger
CalendarIntervalTrigger
DailyTimeIntervalTrigger

CronTrigger

CronTrigger可以满足工作中大部分需求。
一个完整的Cron-Expressions的例子是字符串“0 0 12?* WED“ - 这意味着”每个星期三下午12:00“。

星期
允许的符号 , - * / , - * / , - * / , - * / ?LW , - * / , - * / ?L# , - * /
允许的值 0-59 0-59 0-23 1-31 0-11 1-7 1970-2199

月是0-11,从1月到12月。
星期是1-7,1是星期天。

  • ‘*‘   代表所有值。例如,分钟字段中的’*‘代表’每分钟’。
  • ‘?’   ‘日’和’星期’字段可以使用。代表不确定,例如每个月的15日,不确定是周几,可用’?’代替。’* * * 15 * ? *’
  • ‘,’  用于指定其他值,例如’星期几’字段中的’MON’,’WED’,’FRI’表示’星期一’、’星期三’、’星期五’。
  • ‘/‘ 表示指定增量。例如’0/5 * * * * * *’表示每5s的第0s执行。(注意,不能超过上限,例如0/40,只能在第0s和第40s执行)
  • ‘L’ 表示最后。例如每个月的最后一天。’* * * ? * L ‘表示每月的最后一天。在’星期几’使用表示’周六’如果在星期几加入数字,例如’0 0 0 ? 8 3L 2020’表示2020年9月第三个星期六。’L’还可以指定与最后一天的偏移量。例如’0 0 0 L-3 * ? 2020’表示2020年每月倒数第三天执行。*使用’L’选项时,不要制定列表或者值的范围,例如’1-3’和’L-3’中的’-‘冲突。
  • ‘W’ 表示工作日(周一至周五)。指定’15W’表示’离月15日最近的工作日’。在日字段上写’LW’表示每个月最后一个工作日。
  • ‘#’ 只能用在’星期几’里,例如’6#3’的值表示该月的第三个星期五。如果使用’#’字符,则’星期几’字段里只能有一个表达式。