最近在准备做一个生日提醒的Demo,于是有了这篇博客。咳咳,虽然可以在手机日历设置提醒,但是我们要有自力更生的觉悟以及能力,自己能做当然用自己的嘛。

一、初步了解

百度百科是这样介绍Quartz这个项目的。

Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的程序。

虽然我们可以使用Java的Timer以及线程来实现,但是却不太方便的精确的定位到某年某日某时某分某秒。所以对于这样的需求,使用Quartz是最好的选择

二、引入jar包

网上部分博客说

  要使用Quartz,必须要引入以下这几个包:

1、log4j-1.2.16 2、quartz-2.1.7 3、slf4j-api-1.6.1.jar 4、slf4j-log4j12-1.6.1.jar

这些jar包都在Quartz的包内包含,不过似乎都引入会出现一些冲突,我使用的是2.2.3的jar包,当我引入quartz和log4j的jar,时候发生了冲突。最后引入的jar包如下:

java quartz源码详解 java中quartz_java


注意,我的项目是Java项目,不是J2EE。

三、添加要被执行的任务类

这个类的execute()方法会在触发器被触发的时候执行,即到了预设时间时会被执行。

package Toolkit;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

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

public class MyJob implements Job {
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        System.out.println("现在时间是:" + simpleDateFormat.format(new Date()));
        System.out.println("JobExecutionContext内容是:" + jobExecutionContext.getJobDetail());
    }
}

四、创建、执行任务调度

话不多说,都在代码里~

import Toolkit.MyJob;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

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

import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;

public class Main {
    public void start(){
        //第一步,必需要取得一个调度器
        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        try {
            //任务调度器
            Scheduler scheduler = schedulerFactory.getScheduler();

            //第二步,获取JobDetail对象,来描述Job的实现类及其它相关的静态信息,如Job名字、描述、关联监听器等信息
            JobDetail job = newJob(MyJob.class).withIdentity("job1", "group1").build();

            //复杂的Trigger
            //job1将 从0秒开始 每隔20秒执行一次
            //第三步,获取trigger
            CronTrigger trigger1 = newTrigger()
                    .withIdentity("trigger1","group1")
                    .withSchedule(cronSchedule("0/20 * * * * ?"))
                    .build();

            //第四步,将trigger和job绑定,一个Job可以对应多个Trigger,但一个Trigger只能对应一个Job。
            Date date = scheduler.scheduleJob(job,trigger1);
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println(job.getKey() + "已经被安排执行于:" + simpleDateFormat.format(date) + ",并且以如下重复规则重复执行" + trigger1.getCronExpression() + ",trigger为:" +  trigger1.getKey().getName());

            // 开始执行,start()方法被调用后,计时器就开始工作
            scheduler.start();
            try {
                //主线程等待十分钟
                Thread.sleep(60L * 10000L);
            } catch (Exception e) {  }
            //关闭定时调度,定时器不再工作
            scheduler.shutdown(true);

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

    }

    public static void main(String args[]){
        Main main = new Main();
        main.start();

    }
}

其中有两点需要详细说一说:
1.0/20 * * * * ?,有关通配符的含义请戳这里!
2.一个Job可以绑定多个Trigger,一个Trigger只能绑定在一个Job上。
话不多说,都在代码里。下面给出一个Job绑定多个Trigger的Demo。

import Toolkit.MyJob;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

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

import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;

public class Main {
    public void start(){
        //第一步,必需要取得一个调度器
        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        try {
            //任务调度器
            Scheduler scheduler = schedulerFactory.getScheduler();

            //第二步,获取JobDetail对象,来描述Job的实现类及其它相关的静态信息,如Job名字、描述、关联监听器等信息
            JobDetail job = newJob(MyJob.class).withIdentity("job1", "group1").build();

            //复杂的Trigger
            //job1将 从0秒开始 每隔20秒执行一次
            //第三步,获取trigger
            CronTrigger trigger1 = newTrigger()
                    .withIdentity("trigger1","group1")
                    .withSchedule(cronSchedule("0 35 20 4 9 ?"))
                    .build();
            //注意这里,多个Trigger绑定到一个Job上
            CronTrigger trigger2 = newTrigger()
                    .withIdentity("trigger2","group1")
                    .forJob("job1","group1")
                    .withSchedule(cronSchedule("0/5 * * * * ?"))
                    .build();

            //第四步,将trigger和job绑定,一个Job可以对应多个Trigger,但一个Trigger只能对应一个Job。
            Date date = scheduler.scheduleJob(job,trigger1);
            //注意这里,多个Trigger绑定到一个Job上
            Date date1 = scheduler.scheduleJob(trigger2);
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println(job.getKey() + "已经被安排执行于:" + simpleDateFormat.format(date) + ",并且以如下重复规则重复执行" + trigger1.getCronExpression() + ",trigger为:" +  trigger1.getKey().getName());
            System.err.println(job.getKey() + "已经被安排执行于:" + simpleDateFormat.format(date1) + ",并且以如下重复规则重复执行" + trigger2.getCronExpression() + ",trigger为:" + trigger2.getKey().getName());


            // 开始执行,start()方法被调用后,计时器就开始工作,计时调度中允许放入多个Job
            scheduler.start();
            try {
                //主线程等待十分钟
                Thread.sleep(60L * 10000L);
            } catch (Exception e) {  }
            //关闭定时调度,定时器不再工作
            scheduler.shutdown(true);

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

    }

    public static void main(String args[]){
        Main main = new Main();
        main.start();

    }
}

CronTrigger配置格式:
格式: [秒] [分] [小时] [日] [月] [周] [年]

序号

说明

是否必填

允许填写的值

允许的通配符

1



0-59

, - * /

2



0-59

, - * /

3

小时


0-23

, - * /

4



1-31

, - * ? / L W

5



1-12 or JAN-DEC

, - * /

6



1-7 or SUN-SAT

, - * ? / L #

7



empty 或 1970-2099

, - * /

事例:

CronTrigger配置内容

含义

0 0 12 * * ?

每天12点触发

0 15 10 ? * *

每天10点15分触发

0 15 10 * * ?

每天10点15分触发

0 15 10 * * ? *

每天10点15分触发

0 15 10 * * ? 2005

2005年每天10点15分触发

0 * 14 * * ?

每天下午的 2点到2点59分每分触发

0 0/5 14 * * ?

每天下午的 2点到2点59分(整点开始,每隔5分触发)

0 0/5 14,18 * * ?

每天下午的 2点到2点59分(整点开始,每隔5分触发) 每天下午的 18点到18点59分(整点开始,每隔5分触发)

0 0-5 14 * * ?

每天下午的 2点到2点05分每分触发

0 10,44 14 ? 3 WED

3月分每周三下午的 2点10分和2点44分触发

0 15 10 ? * MON-FRI

从周一到周五每天上午的10点15分触发

0 15 10 15 * ?

每月15号上午10点15分触发

0 15 10 L * ?

每月最后一天的10点15分触发

0 15 10 ? * 6L

每月最后一周的星期五的10点15分触发

0 15 10 ? * 6L 2002-2005

从2002年到2005年每月最后一周的星期五的10点15分触发

0 15 10 ? * 6#3

每月的第三周的星期五开始触发

0 0 12 1/5 * ?

每月的第一个中午开始每隔5天触发一次

0 11 11 11 11 ?

每年的11月11号 11点11分触发(光棍节)