scheduler.shutDown(true)不执行job即停止

本文深入解析了Quartz Scheduler的工作机制,并针对使用中遇到的问题提供了解决方案,特别是关于`shutdown(true)`方法的误解及其正确使用方法。通过案例分析,详细解释了如何在避免误操作的情况下确保任务执行完毕后再关闭调度器。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

package schedule;

import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;

import org.quartz.CronExpression;
import org.quartz.CronTrigger;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.impl.JobDetailImpl;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.triggers.CronTriggerImpl;
import org.quartz.impl.triggers.SimpleTriggerImpl;

public class TriggerTest {
	public static void main(String[] args) throws SchedulerException, ParseException, InterruptedException {
		testSimpleTrigger();
		
		//testCronTrigger();
	}
	
	private static void testSimpleTrigger() throws SchedulerException, InterruptedException{
		JobDetailImpl jobDetail = new JobDetailImpl();
		jobDetail.setGroup("myGroup");
		jobDetail.setJobClass(MyJob.class);
		jobDetail.setName("jobDetail");
		
		SimpleTriggerImpl trigger = new SimpleTriggerImpl();
		trigger.setStartTime(new Date());
		trigger.setName("myTrigger");
		trigger.setRepeatInterval(1000);
		trigger.setRepeatCount(1);
		
		/*job在endTime时不再执行,但scheduler并未shutdown
		 * Date c = new Date();
		c.setTime(System.currentTimeMillis()+2000L);
		trigger.setEndTime(c);*/
		
		
		Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
		scheduler.scheduleJob(jobDetail, trigger);
		scheduler.start();
		scheduler.shutdown(true);
			
	}
	
}

执行时发现MyJob一次也没执行,scheduler就shutDown了。后来在网上看到一篇回答

http://stackoverflow.com/questions/15928980/quartz-scheduler-shuts-down-before-job-execution

答主提到了这些:I think you're misunderstanding the purpose of scheduler.shutdown(true); It will wait for executing jobs to finish, but it will NOT wait for scheduled jobs to start and finish. Your job is not starting before you shutdown the scheduler.You could put a Thread.sleep(wait); before you shut it down. 

原来是shutDown(true)只是等待scheduler执行完,而不是等等job完成。试着按答主的方法加了,即

package schedule;

import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;

import org.quartz.CronExpression;
import org.quartz.CronTrigger;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.impl.JobDetailImpl;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.triggers.CronTriggerImpl;
import org.quartz.impl.triggers.SimpleTriggerImpl;

public class TriggerTest {
	public static void main(String[] args) throws SchedulerException, ParseException, InterruptedException {
		testSimpleTrigger();
		
		//testCronTrigger();
	}
	
	private static void testSimpleTrigger() throws SchedulerException, InterruptedException{
		JobDetailImpl jobDetail = new JobDetailImpl();
		jobDetail.setGroup("myGroup");
		jobDetail.setJobClass(MyJob.class);
		jobDetail.setName("jobDetail");
		
		SimpleTriggerImpl trigger = new SimpleTriggerImpl();
		trigger.setStartTime(new Date());
		trigger.setName("myTrigger");
		trigger.setRepeatInterval(1000);
		trigger.setRepeatCount(1);
		
		/*job在endTime时不再执行,但scheduler并未shutdown
		 * Date c = new Date();
		c.setTime(System.currentTimeMillis()+2000L);
		trigger.setEndTime(c);*/
		
		
		Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
		scheduler.scheduleJob(jobDetail, trigger);
		scheduler.start();
		Thread.sleep(2000);//不加这一句,会在schedule触发时即shutdown,而不是job执行完shutdown
		scheduler.shutdown(true);
			
	}
}

给job留够执行完成的时间,则在job重复执行一次后,scheduler关闭

转载于:https://my.oschina.net/u/2430057/blog/531258

<think>好的,我现在需要帮助用户分析他们提供的Quartz调度框架的代码,并解释如何将任务触发机制改为基于时间间隔的模式。首先,我需要回顾用户之前的问题,他们之前询问过如何将Quartz改成时间间隔触发,并且得到了两种方法:SimpleTrigger和CronTrigger。现在用户提供的代码看起来使用了同的类,比如JobDetailImpl和CalendarIntervalTriggerImpl,这可能意味着他们使用的是较旧版本的Quartz,或者同的配置方式。 首先,我需要检查用户提供的代码结构。用户创建了一个JobDetailImpl实例,并设置了描述、组、Job类、键值以及持久性。然后创建了一个CalendarIntervalTriggerImpl触发器,设置了开始时间、重复间隔为7秒,组和名称,最后通过调度器安排了任务和触发器。 接下来,我需要确定用户可能的需求。他们可能在使用旧版Quartz,或者可能混淆了同触发器的类型。因为之前的回答中提到了SimpleTrigger和CronTrigger,而这里使用的是CalendarIntervalTriggerImpl,这属于另一种触发器类型,可能需要解释这种触发器的特点。 然后,我需要分析代码中的关键点。例如,JobDetailImpl在较新的Quartz版本中可能已被弃用,推荐使用JobBuilder。同样,CalendarIntervalTriggerImpl可能属于旧版API,而CalendarIntervalTrigger更常见于新版。需要指出这些类可能已过时,建议使用新的构建方式,如JobBuilder和TriggerBuilder。 另外,用户设置的重复间隔为7秒,使用CalendarIntervalTriggerImpl,但CalendarIntervalTrigger通常按日历间隔(如天、月)触发,对于秒级的间隔可能如SimpleTrigger精确。需要提醒用户这一点,可能推荐使用SimpleTrigger更合适。 还要检查代码中的潜在问题。例如,JobDetail的key设置是否正确,是否与Trigger的组和名称一致。用户可能在这里有重复设置,比如JobKey和Trigger的组名和名称是否匹配,是否需要保持一致? 然后,我需要考虑用户可能的疑问:为什么他们的代码和之前介绍的方法同?是否有兼容性问题?是否需要迁移到新API?如何确保时间间隔准确? 此外,用户的代码中使用了DateBuilder.IntervalUnit,这可能是一个错误,因为CalendarIntervalTriggerImpl通常有自己的设置方法。需要指出正确的设置方式,例如setRepeatIntervalUnit应该使用DateBuilder.IntervalUnit还是其他枚举类型,是否存在导入错误? 最后,要总结用户的代码,指出各部分的作用,可能存在的问题,并提供改进建议,比如使用新API、选择合适的触发器类型,并强调调度器的启动和配置注意事项。</think>以下是您提供的 Quartz 调度代码的逐行解析及优化建议: --- ### **代码结构解析** ```java // 创建 JobDetailImpl 实例(旧版API,已过时) JobDetailImpl jobDetail = new JobDetailImpl(); jobDetail.setDescription("Online User Check job"); jobDetail.setGroup("onlineuser_group"); jobDetail.setJobClass(OnlineUserCheckJob.class); jobDetail.setKey(JobKey.jobKey("onlineuser_job", "onlineuser_group")); jobDetail.setDurability(true); // 创建 CalendarIntervalTriggerImpl 触发器(旧版API) CalendarIntervalTriggerImpl intervalTrigger = new CalendarIntervalTriggerImpl(); Calendar startTime = Calendar.getInstance(); intervalTrigger.setStartTime(startTime.getTime()); DateBuilder.IntervalUnit interValUnit = IntervalUnit.SECOND; intervalTrigger.setRepeatInterval(7); // 间隔7秒 intervalTrigger.setRepeatIntervalUnit(interValUnit); intervalTrigger.setGroup("onlineuser_group"); intervalTrigger.setName("onlineuser_job"); // 注册任务和触发器到调度器 scheduler.scheduleJob(jobDetail, intervalTrigger); ``` --- ### **关键问题说明** 1. **过时的API使用**: - `JobDetailImpl` 和 `CalendarIntervalTriggerImpl` 是 Quartz 1.x 的类,**Quartz 2.x+ 已弃用**,建议改用 `JobBuilder` 和 `TriggerBuilder`。 - 示例修正: ```java JobDetail jobDetail = JobBuilder.newJob(OnlineUserCheckJob.class) .withIdentity("onlineuser_job", "onlineuser_group") .withDescription("Online User Check job") .storeDurably(true) // 持久化设置 .build(); ``` 2. **触发器类型选择当**: - `CalendarIntervalTrigger` 适用于按日历单位(如天、月)触发,**秒级间隔建议使用 `SimpleTrigger`**。 - 示例修正: ```java Trigger trigger = TriggerBuilder.newTrigger() .withIdentity("onlineuser_job", "onlineuser_group") .startNow() .withSchedule(SimpleScheduleBuilder.simpleSchedule() .withIntervalInSeconds(7) // 精确到秒的间隔 .repeatForever()) .build(); ``` 3. **重复定义分组**: - `jobDetail.setGroup("onlineuser_group")` 和 `jobDetail.setKey(JobKey.jobKey("onlineuser_job", "onlineuser_group"))` 重复指定了组名,保留 `withIdentity()` 即可。 --- ### **优化后的完整代码** ```java // 使用 JobBuilder 创建 JobDetail(推荐方式) JobDetail jobDetail = JobBuilder.newJob(OnlineUserCheckJob.class) .withIdentity("onlineuser_job", "onlineuser_group") .withDescription("Online User Check job") .storeDurably(true) // 持久化配置 .build(); // 使用 SimpleTrigger 定义精确间隔 Trigger trigger = TriggerBuilder.newTrigger() .withIdentity("onlineuser_trigger", "onlineuser_group") // 触发器名称需唯一 .startNow() .withSchedule(SimpleScheduleBuilder.simpleSchedule() .withIntervalInSeconds(7) // 每7秒执行一次 .repeatForever()) .build(); // 注册到调度器 scheduler.scheduleJob(jobDetail, trigger); ``` --- ### **注意事项** 1. **调度器启动**: - 确保调用 `scheduler.start()` 启动任务执行。 - 停止时调用 `scheduler.shutdown(true)` 释放资源。 2. **时间间隔精度**: - `SimpleTrigger` 的秒级间隔依赖系统时钟,**长任务可能延迟**。 - 如需高精度,可配置线程池: ```properties org.quartz.threadPool.threadCount = 10 // 增大线程数 ``` 3. **任务幂等性**: - 短间隔任务需确保逻辑可重复执行(如数据库操作需加锁或去重)。 --- ### **总结** - **优先使用新版API**(`JobBuilder`/`TriggerBuilder`),避免直接实例化底层类。 - **秒级间隔选择 `SimpleTrigger`**,日历规则(如每月执行)再用 `CalendarIntervalTrigger`。 - 完整示例参考:[Quartz Official Documentation](https://www.quartz-scheduler.org/documentation/)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值