spring中的quartz调度问题
关键字: spring quartz 线程池 多线程
1 、SchedulerFactoryBean会自动启动。
当在 spring 文件中定义了多个SchedulerFactoryBean实例时,一定要小心,因为这些 ScheduleFactoryBean 自从 load 进程序里,就会自动启动。如果要手动控制,注意要将autoStartup属性设置为 false 。
2 、SchedulerFactoryBean暴露的是 Scheduler ,而不是SchedulerFactoryBean。
SchedulerFactoryBean实现了 FactoryBean 接口,必须实现两个方法,一个是getObjectType,另外一个则是 getObject; 其中 getObjectType 定义了返回的类型应该为Scheduler,而 getObject 指定了返回的是其一个重要属性 scheduler ,这个 scheduler 就是我们要获得的调度。
若在配置文件里为SchedulerFactoryBean定义了 id 属性为 "scheduler" ,则在程序里调用 getBean 时,需要注意 getBean("scheduler") 返回的是Scheduler对象
3 、
SchedulerFactoryBean中有两个很重要的属性,一个是 scheduler ,另外一个是schedulerFactoryClass, spring 通过用schedulerFactoryClass做代理来产生调度,并把它赋给 scheduler 。
private Class schedulerFactoryClass = StdSchedulerFactory.class;
// 如果你没有指定schedulerFactoryClass ,那么它用的是 quartz 中自带的调度工厂,
this.scheduler = createScheduler(schedulerFactory, this.schedulerName);
// 这里的schedulerName默认传进来是空的,其实如果你不是用自己定义的schedulerFactoryClass
// 恐怕也没有什么意义,因为createScheduler是这样调用的
return schedulerFactory.getScheduler();
// 显然schedulerName并没有用到,除非是你自行写一个schedulerFactory,并做好相应处理,
// 否则返回的这个 scheduler 一定是一个指定名称的调度
Scheduler sched = schedRep.lookup(getSchedulerName());
// 这个 sched 就是要代理生成的schedule r ,getSchedulerName只有一句话,如下:
cfg.getStringProperty(PROP_SCHED_INSTANCE_NAME,"QuartzScheduler");
// 如果我们没有使用一些特殊的机制,那么返回的只能是一个固定的字符串。
如上说述,如果我们希望不进行改造,就在 spring 的配置文件中定义多个调度的方法来实现我们个性化的任务安排时,可能并不可行。因为 spring 配置的 scheduler 只能有一个,即使你定义了多个调度,那么其实实现的只有一个,只是所有你希望指向不同调度的 id 都会指向它罢了,而这个调度会包含了其它所有调度中的任务。
4 、抱错:org.quartz.SchedulerException: Repeat Interval cannot be zero
场景:该错误通常是在引用了 SimpleTriggerBean 的时候没有为 repeatCount 和repeatInterval赋值发生的,很奇怪, SimpleTriggerBean 有一个空构造函数,在里面直接为 repeatCount 赋了一个REPEAT_INDEFINITELY,这样,当其进入 validate 函数时,会抱错。而 quartz 中的 SimpleTrigger 这两个属性默认值均为 0 ,不懂 spring 中为何这样处理。
5 、 quartz 和 crontab 的区别
a 、 quartz 属于用户级别, crontab 则属于系统级别;
b 、 quartz 调度的线程,所有线程共享一个 jvm ; crontab 调度的则是应用,每个应用都独立的占用资源。
6 、 quartz 中加入并发多线程分析
a 、 quartz 本身是有线程池支持的,这个可以用org.quartz.threadPool.threadCount属性来设置线程池大小, quartz 的任务可以由 quartz 的线程池自动调度
b 、对每个任务也可能起多线程,但是需要对并发数量做控制,可以考虑使用 commons-pools 提供的对象池机制