关于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);
}
}
}
最后的执行结果为
注意,时间是从0开始的,也就是
24,60,60的数字可能会注册不成功,只能对应0