欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

关于Quartz定时任务的使用

程序员文章站 2024-03-22 16:01:34
...
  使用场景:不同的学校,都有一个或多个多个负责人需要接收到教师早上到校的记录。不同学校的接收时间不相同,可以灵活配置。
    以上使用场景,简单的Timer定时器也可以满足程序的需求。自己写一个定时任务的连接池,记录对应时间的触发,传入参数,执行程序时需要知道是哪个学校触发的执行。
    以上的使用场景,有现成的*,Quartz可以满足以上的使用方式。
    
    使用前需要明确几个概念:
    1、Scheduler,一个容器,存放Trigger和Job。程序里注册一个Scheduler即可。
        Trigger和JobDetail可以注册到Scheduler中,两者在Scheduler中拥有各自的组及名称,组及名称是Scheduler查找定位容器中某一对象的依据,Trigger的组及名称必须唯一,JobDetail的组和名称也必须唯一(但可以和Trigger的组和名称相同,因为它们是不同类型的)
         这样我可以很方便地根据学校的名称来找到对应的定时任务,进行修改发送短信的时间
    2、Job 是一个接口,只有一个方法void execute(JobExecutionContext context) ,也就是任务的执行程序,我的发信息的方法,就是需要放在里面。学校的信息等参数,可以保存到JobDataMap,通过调用方法拿到
    3、JobDetail :Quartz在每次执行Job时,都重新创建一个Job实例,所以它不直接接受一个Job的实例,相反它接收一个Job实现类,以便运行时通过newInstance()的反射机制实例化Job。这个看不懂就看不懂吧,知道怎么用就行了,其实我也没太明白
    4、Trigger:触发器,定义的触发规则,其中CronTrigger规则功能非常非常强大,不只可以规定每天几点几分执行,还可以很方便地规定每周几执行,每月几号执行,每年的某月某日执行等等……
    5、Calendar:它是一些日历特定时间点的集合,一个Trigger可以和多个Calendar关联,以便排除或包含某些时间点。

其他的类似于线程池等概念没有用到,就不再多说了。
以下是我写的测试代码,属于一个最简单的Quartz应用了

首先定义了两个不两同的Job,实现Job接口中的execute方法:
public class TestJob1 implements Job{
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    @Override
    public void execute(JobExecutionContext jec) throws JobExecutionException {
        System.out.println("【"+sdf.format(new Date())+"】名称为【TestJob1】触发器为【"+jec.getTrigger().getKey().getName()+"】:" + jec.getJobDetail().getJobDataMap().getString("childDB"));
    }
    
}

public class TestJob2 implements Job{
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    @Override
    public void execute(JobExecutionContext jec) throws JobExecutionException {
        System.out.println("【"+sdf.format(new Date())+"】名称为【TestJob2】触发器为【"+jec.getTrigger().getKey().getName()+"】:" + jec.getJobDetail().getJobDataMap().getString("childDB"));
    } 
}

然后注册了几个任务,包括每0秒执行,每1秒执行,每10秒执行,每20秒执行……
public class TriggerTest {

    static Scheduler scheduler = null;

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws SchedulerException {
        scheduler = StdSchedulerFactory.getDefaultScheduler();
        scheduler.start();
        
        addOneTrigger("01","*","*","每1秒执行1",1);
        addOneTrigger("01","*","*","每1秒执行2",2);
        addOneTrigger("10","*","*","每10秒执行1",1);
        addOneTrigger("10","*","*","每10秒执行2",2);
        addOneTrigger("20","*","*","每20秒执行1",1);
        addOneTrigger("20","*","*","每20秒执行2",2);
        addOneTrigger("30","*","*","每30秒执行1",1);
        addOneTrigger("30","*","*","每30秒执行2",2);
        addOneTrigger("40","*","*","每40秒执行1",1);
        addOneTrigger("40","*","*","每40秒执行2",2);
        addOneTrigger("50","*","*","每50秒执行1",1);
        addOneTrigger("50","*","*","每50秒执行2",2);
        addOneTrigger("00","*","*","每0秒执行1",1);
        addOneTrigger("00","*","*","每0秒执行2",2);
    }

    public static synchronized void addOneTrigger(String second, String minute, String hour, String jobName,int index) {
        try {
            String text = second + " " + minute + " " + hour + " * * ?";
            CronTrigger trigger;
         
                //加入这个调度
                trigger = newTrigger().
                        withIdentity(jobName).
                        withSchedule(CronScheduleBuilder.cronSchedule(text)).
                        build();
                
            //定义一个JobDetail
            JobDetail job = newJob(index==1?TestJob1.class : TestJob2.class ) //两个不同的Job
                    
                    .withIdentity(jobName) //定义name,也可以加上group属性
                    .usingJobData("childDB", jobName) //这个是变量
                    .build();
            scheduler.scheduleJob(job, trigger);
        } catch (SchedulerException ex) {
            Logger.getLogger(TriggerTest.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

}
最后的执行结果为

关于Quartz定时任务的使用
 注意,时间是从0开始的,也就是 24,60,60的数字可能会注册不成功,只能对应0