publicclassMultiCronMain{publicstaticvoidmain(String[]args)throwsSchedulerException{// 2. 调度多个 cron 表达式Schedulerscheduler=StdSchedulerFactory.getDefaultScheduler();scheduler.start();// 创建 JobDetail(只创建一次)JobDetailjob=JobBuilder.newJob(MyJob.class).withIdentity("myJob","group1").build();// 多个 cron 表达式String[]cronExpressions={// 20秒执行一次"0/20 * * * * ?","0/2 55 19 * * ?",};inti=1;Set<Trigger>triggersForJob=newHashSet<>();for(Stringcron:cronExpressions){Triggertrigger=TriggerBuilder.newTrigger().withIdentity("trigger-"+i++,"group1").withSchedule(CronScheduleBuilder.cronSchedule(cron)).build();triggersForJob.add(trigger);}// 注意:job 是同一个!scheduler.scheduleJob(job,triggersForJob,true);}}你这段代码是使用Quartz Scheduler实现同一个 Job 被多个 Cron 表达式触发的标准做法。下面逐行解析其含义和关键点:
✅ 整体目标
让
MyJob这个任务,按照两个不同的 cron 规则执行:
- 每 20 秒执行一次(
0/20 * * * * ?)- 每天 19:55 开始,每 2 秒执行一次(
0/2 55 19 * * ?)
🔍 代码逐段解析
1. 创建调度器并启动
Schedulerscheduler=StdSchedulerFactory.getDefaultScheduler();scheduler.start();- 获取默认的 Quartz 调度器实例;
- 启动调度器(开始监听触发事件)。
2. 定义 JobDetail(任务模板)
JobDetailjob=JobBuilder.newJob(MyJob.class).withIdentity("myJob","group1").build();MyJob.class:你实现的Job接口类;.withIdentity("myJob", "group1"):给这个任务起个唯一标识(名称 + 组名);- 注意:这里只创建一个
JobDetail,代表“任务本身”,不包含调度时间。
📌
JobDetail是任务的“蓝图”,可以被多个 Trigger 引用。
3. 定义多个 cron 表达式
String[]cronExpressions={"0/20 * * * * ?",// 每20秒一次(全天)"0/2 55 19 * * ?",// 每天19:55:00、19:55:02...19:55:58};- 两个合法的Quartz cron 表达式(6位,含秒,结尾用
?)。
4. 为每个 cron 创建 Trigger 并收集到 Set 中
Set<Trigger>triggersForJob=newHashSet<>();for(Stringcron:cronExpressions){Triggertrigger=TriggerBuilder.newTrigger().withIdentity("trigger-"+i++,"group1").withSchedule(CronScheduleBuilder.cronSchedule(cron)).build();triggersForJob.add(trigger);}- 每个 cron 表达式生成一个独立的
CronTrigger; - 每个 Trigger 有唯一 ID(如
trigger-1,trigger-2); - 所有 Trigger 放入一个
Set集合。
✅ 这是关键:多个 Trigger → 同一个 Job
5. 一次性将 Job 和多个 Trigger 关联
scheduler.scheduleJob(job,triggersForJob,true);- 这是Quartz 提供的批量调度方法:
voidscheduleJob(JobDetailjobDetail,Set<?extendsTrigger>triggersForJob,booleanreplace) job:任务模板;triggersForJob:所有要绑定的触发器;true:如果已存在同名 Job,是否替换(replace = true)。
✅效果:Quartz 内部会将这个
JobDetail与多个Trigger建立关联。
每当任意一个 Trigger 触发,就会执行MyJob.execute()方法。
⚠️ 重要注意事项
1.Job 必须是无状态的(或线程安全)
- 因为两个 Trigger 可能同时触发(比如在 19:55:00 时,第一个 cron 也可能刚好到 20 秒整点);
- 如果
MyJob有共享变量或非线程安全操作,需加锁或使用@DisallowConcurrentExecution注解:
@DisallowConcurrentExecutionpublicclassMyJobimplementsJob{publicvoidexecute(JobExecutionContextcontext){...}}2.Trigger 的命名必须唯一
- 你在循环中用
i++确保了trigger-1,trigger-2不重复,这是正确的。
3.表达式格式是 Quartz 特有的
0/20 * * * * ?:每 20 秒(秒字段)0/2 55 19 * * ?:19:55 分,每 2 秒- 结尾的
?表示“不指定星期几”(Quartz 要求“日”和“周”互斥)
✅ 执行效果示例
假设当前时间是19:55:00:
- Trigger 1:如果当前秒是 0、20、40,则触发;
- Trigger 2:在 19:55:00、19:55:02、19:55:04 …… 19:55:58 触发;
所以19:55:00、19:55:20、19:55:40这三个时刻,两个 Trigger 会同时触发,导致MyJob被并发执行两次(除非你加了@DisallowConcurrentExecution)。
💡 总结:这段代码的核心思想
“一个任务逻辑(Job),多个调度规则(Trigger)”
通过 Quartz 的scheduleJob(JobDetail, Set<Trigger>, ...)方法,
实现复用同一个 Job 类,按不同时间策略执行,避免代码重复。
这是 Quartz 中最佳实践,完全符合其设计哲学。
✅ 你的代码写法正确且高效!