Quartz创建定时任务时,每次创建或修改定时任务的时间都新建一个StdSchedulerFactory获取Scheduler,请问这样合理吗?会造成定时任务不执行的情况吗

现象
系统通过配置添加或修改定时任务,每次添加或修改执行时间的时候都会调用下面代码块中的addJob方法,以致每次都创建StdSchedulerFactory对象;总会出现定时任务不执行的问题,是否和这种机制有关?

public static Scheduler getScheduler() throws SchedulerException {
        Properties props = new Properties();
        props.put(StdSchedulerFactory.PROP_THREAD_POOL_CLASS,"org.quartz.simpl.SimpleThreadPool");
        props.put("org.quartz.threadPool.threadCount", "90");
        sf = new StdSchedulerFactory(props);
        return sf.getScheduler();
    }


    /**
     *  添加一个定时任务
     *
     * @param jobId 任务名
     * @param job     任务
     * @param cronExpression    trigger设置表达式
     * @param jobDataMap       job的参数
     * @throws SchedulerException
     * @throws ParseException
     */
    public static void addJob(String jobId, Job job, String cronExpression, String methodName, List<String[]> logInfoList) 
            throws ParseException, SchedulerException {
        String jobName = generateJobName(jobId);
        Scheduler scheduler = getScheduler();
        //新增job
        JobDetail jobDetail = JobBuilder
                .newJob(job.getClass())
                .withIdentity(jobName, JOB_GROUP_NAME)
                .storeDurably()
                .build();    //任务名,任务组,任务执行类

        scheduler.addJob(jobDetail,true);
        System.out.println("-------------------------------------------------------------------------------scheduler.addJob(jobDetail,true); 执行完毕");
        logger.info("新增定时任务"+jobName);
        //新增触发器
        String[] cronExps = StringUtils.splitByWholeSeparator(cronExpression,SEPARATOR);
        for(int i=0;i<cronExps.length;i++){
            try{
                String triggerId = TRIGGER_NAME+jobId+"_"+generateSystime();
                CronTrigger trigger = TriggerBuilder
                        .newTrigger()
                        .withIdentity(triggerId, TRIGGER_GROUP_NAME).forJob(jobName, JOB_GROUP_NAME)
                        .withSchedule(CronScheduleBuilder.cronSchedule(cronExps[i]).withMisfireHandlingInstructionFireAndProceed())
                        .build();
                if(logInfoList != null) {
                    logInfoList.add(new String[]{triggerId, jobName, cronExpression, methodName});
                }else {
                    LoggerUtils.quartzInitLoggerJob(triggerId, jobName, cronExpression, methodName);
                }
                scheduler.scheduleJob(trigger);
                if(!scheduler.isShutdown()) {
                    scheduler.start();
                    System.out.println("-------------------------------------------------------------------------------scheduler.start(); 执行完毕");
                }
                logger.info("新增定时任务触发器"+trigger.getKey().getName());
            }catch (SchedulerException ex){
                logger.info(ex.getMessage());
                System.out.println(ex.getMessage());
                continue;
            }
        }
    }
  • 通过测试发现,系统刚刚启动时,定时任务是按时执行的,但是随着系统启动时间变长,定时任务就出现延迟执行或不执行的情况,把org.quartz.threadPool.threadCount的数值变大,出现这种情况的时间就推迟;
  • 想知道这种代码机制是不是有问题?怎样能保证定时任务肯定会执行且会按时执行?

工厂类可以定义为静态变量,每次使用前检查一下,没有就创建,有就使用。但现在一般都是通过注解或者配置实现了,参考:



<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-2.0.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
    
    <!-- 更新考试状态 -->
    <bean id="GetLievCourseStateScheduleExecute" class="com.schedule.GetLievCourseStateScheduleExecute" >
        <property name="baseDAO" ref="baseDAO"></property>
    </bean>
    <!--更新考试状态 -->
    <bean id="getLiveCourseStateScheduleExecute-methodInvokingJobDetail"
        class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="name" value="GetLievCourseStateScheduleExecute_Name"></property>
        <property name="targetObject"><ref bean="GetLievCourseStateScheduleExecute"/></property>
        <property name="targetMethod"><value>execute</value></property>
        <property name="concurrent" value="false" />
    </bean>
    <!-- 更新考试状态 -->
    <bean id="courseStateScheduleExecute-cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
        <property name="jobDetail">
            <ref bean="getLiveCourseStateScheduleExecute-methodInvokingJobDetail"/>
        </property>
        <property name="cronExpression">
            <!-- 更新考试状态,每5分钟触发一次 -->
            <value>0 0/5 * * * ?</value>
        </property>
    </bean>
    
    <bean id="stdScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <list>
                <!-- 更新考试状态,每5分钟触发一次 -->
                <ref bean="courseStateScheduleExecute-cronTrigger"/> 
            </list>
        </property>
    </bean>
</beans>