quartz源码浅析

1.简介

Quartz是一个开源的作业调度框架,它完全由 Java写成,并设计用于 J2SE J2EE应用中。它提供了巨大的灵活性而不牺牲简单性。你能够用它来为执行一个作业而创建简单的或复杂的调度。

2.原理


quartz源码浅析_第1张图片
 

参考http://ssuupv.blog.163.com/blog/static/146156722013829111028966/

3.以内存运行信息方式分析源码

3.1 测试代码

Java代码
  1. public static void main(String[] args) {  
  2.         SimpleDateFormat DateFormat = new SimpleDateFormat("yyyyMMddHHmmss");  
  3.         Date d = new Date();  
  4.         String returnstr = DateFormat.format(d);  
  5.         try {  
  6.             System.out.println(returnstr + "【系统启动】");  
  7.             QuartzManager.addJob("11", TestJob.class"0/2 * * * * ?"); //每2秒钟执行一次    
  8.         } catch (Exception e) {  
  9.             e.printStackTrace();  
  10.         }  
  11.         try {  
  12.             System.out.println("【系统启动】");  
  13.             QuartzManager.start();  
  14.         } catch (Exception e) {  
  15.             e.printStackTrace();  
  16.         }  
  17.     }  

 QuartzManager:

Java代码
  1. /** */  
  2.     /**  
  3.     *  添加一个定时任务,使用默认的任务组名,触发器名,触发器组名  
  4.     * @param jobName 任务名  
  5.     * @param job     任务  
  6.     * @param time    时间设置,参考quartz说明文档  
  7.     * @throws SchedulerException  
  8.     * @throws ParseException  
  9.     */  
  10.     @SuppressWarnings("deprecation")  
  11.     public static void addJob(String jobName, Classextends Job> jobClazz, String time) throws SchedulerException,  
  12.             ParseException {  
  13.         Scheduler sched = sf.getScheduler();  
  14.         JobDetail jobDetail = new JobDetailImpl(jobName, JOB_GROUP_NAME, jobClazz);//任务名,任务组,任务执行类    
  15.         //触发器    
  16.         CronTriggerImpl trigger = new CronTriggerImpl(jobName, TRIGGER_GROUP_NAME);//触发器名,触发器组    
  17.         trigger.setCronExpression(time);//触发器时间设定    
  18.         sched.scheduleJob(jobDetail, trigger);  
  19.         //启动    
  20.         if (!sched.isShutdown())  
  21.             sched.start();  
  22.   
  23.     }  
  24.   
  25.     public static void start() throws SchedulerException, ParseException {  
  26.         Scheduler sched = sf.getScheduler();  
  27.         //启动    
  28.         if (!sched.isShutdown())  
  29.             sched.start();  
  30.   
  31.     }  

 

TestJob:

Java代码
  1. public class TestJob implements Job {  
  2.     private final static SimpleDateFormat DateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
  3.   
  4.     public void execute(JobExecutionContext context) throws JobExecutionException {  
  5.         System.out.println(DateFormat.format(new Date()) + "★★★★★★★★★★★");  
  6.     }  
  7. }  

 3.2代码分析

3.2.1首先通过SchedulerFactory得到StdScheduler


quartz源码浅析_第2张图片
 

Java代码
  1. private Scheduler instantiate() throws SchedulerException {  
  2.         if (cfg == null) {  
  3.             initialize();  
  4.         }  
  5.   
  6.         if (initException != null) {  
  7.             throw initException;  
  8.         }  
  9.   
  10.         JobStore js = null;  
  11.         ThreadPool tp = null;  
  12.         QuartzScheduler qs = null;  
  13.         DBConnectionManager dbMgr = null;  
  14.         String instanceIdGeneratorClass = null;  
  15.         Properties tProps = null;  
  16.         String userTXLocation = null;  
  17.         boolean wrapJobInTx = false;  
  18.         boolean autoId = false;  
  19.         long idleWaitTime = -1;  
  20.         long dbFailureRetry = -1;  
  21.         String classLoadHelperClass;  
  22.         String jobFactoryClass;  
  23.         ThreadExecutor threadExecutor;  
  24.   
  25.   
  26.         SchedulerRepository schedRep = SchedulerRepository.getInstance();  
  27.   
  28.         // Get Scheduler Properties  
  29.         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
  30.   
  31.         String schedName = cfg.getStringProperty(PROP_SCHED_INSTANCE_NAME,  
  32.                 "QuartzScheduler");  
  33.   
  34.         String threadName = cfg.getStringProperty(PROP_SCHED_THREAD_NAME,  
  35.                 schedName + "_QuartzSchedulerThread");  
  36.   
  37.         String schedInstId = cfg.getStringProperty(PROP_SCHED_INSTANCE_ID,  
  38.                 DEFAULT_INSTANCE_ID);  
  39.   
  40.         if (schedInstId.equals(AUTO_GENERATE_INSTANCE_ID)) {  
  41.             autoId = true;  
  42.             instanceIdGeneratorClass = cfg.getStringProperty(  
  43.                     PROP_SCHED_INSTANCE_ID_GENERATOR_CLASS,  
  44.                     "org.quartz.simpl.SimpleInstanceIdGenerator");  
  45.         }  
  46.         else if (schedInstId.equals(SYSTEM_PROPERTY_AS_INSTANCE_ID)) {  
  47.             autoId = true;  
  48.             instanceIdGeneratorClass =   
  49.                     "org.quartz.simpl.SystemPropertyInstanceIdGenerator";  
  50.         }  
  51.   
  52.         userTXLocation = cfg.getStringProperty(PROP_SCHED_USER_TX_URL,  
  53.                 userTXLocation);  
  54.         if (userTXLocation != null && userTXLocation.trim().length() == 0) {  
  55.             userTXLocation = null;  
  56.         }  
  57.   
  58.         classLoadHelperClass = cfg.getStringProperty(  
  59.                 PROP_SCHED_CLASS_LOAD_HELPER_CLASS,  
  60.                 "org.quartz.simpl.CascadingClassLoadHelper");  
  61.         wrapJobInTx = cfg.getBooleanProperty(PROP_SCHED_WRAP_JOB_IN_USER_TX,  
  62.                 wrapJobInTx);  
  63.   
  64.         jobFactoryClass = cfg.getStringProperty(  
  65.                 PROP_SCHED_JOB_FACTORY_CLASS, null);  
  66.   
  67.         idleWaitTime = cfg.getLongProperty(PROP_SCHED_IDLE_WAIT_TIME,  
  68.                 idleWaitTime);  
  69.         dbFailureRetry = cfg.getLongProperty(  
  70.                 PROP_SCHED_DB_FAILURE_RETRY_INTERVAL, dbFailureRetry);  
  71.   
  72.         boolean makeSchedulerThreadDaemon =  
  73.             cfg.getBooleanProperty(PROP_SCHED_MAKE_SCHEDULER_THREAD_DAEMON);  
  74.   
  75.         boolean threadsInheritInitalizersClassLoader =  
  76.             cfg.getBooleanProperty(PROP_SCHED_SCHEDULER_THREADS_INHERIT_CONTEXT_CLASS_LOADER_OF_INITIALIZING_THREAD);  
  77.   
  78.         boolean skipUpdateCheck = cfg.getBooleanProperty(PROP_SCHED_SKIP_UPDATE_CHECK, false);  
  79.         long batchTimeWindow = cfg.getLongProperty(PROP_SCHED_BATCH_TIME_WINDOW, 0L);  
  80.         int maxBatchSize = cfg.getIntProperty(PROP_SCHED_MAX_BATCH_SIZE, 1);  
  81.   
  82.         boolean interruptJobsOnShutdown = cfg.getBooleanProperty(PROP_SCHED_INTERRUPT_JOBS_ON_SHUTDOWN, false);  
  83.         boolean interruptJobsOnShutdownWithWait = cfg.getBooleanProperty(PROP_SCHED_INTERRUPT_JOBS_ON_SHUTDOWN_WITH_WAIT, false);  
  84.   
  85.         boolean jmxExport = cfg.getBooleanProperty(PROP_SCHED_JMX_EXPORT);  
  86.         String jmxObjectName = cfg.getStringProperty(PROP_SCHED_JMX_OBJECT_NAME);  
  87.           
  88.         boolean jmxProxy = cfg.getBooleanProperty(PROP_SCHED_JMX_PROXY);  
  89.         String jmxProxyClass = cfg.getStringProperty(PROP_SCHED_JMX_PROXY_CLASS);  
  90.   
  91.         boolean rmiExport = cfg.getBooleanProperty(PROP_SCHED_RMI_EXPORT, false);  
  92.         boolean rmiProxy = cfg.getBooleanProperty(PROP_SCHED_RMI_PROXY, false);  
  93.         String rmiHost = cfg.getStringProperty(PROP_SCHED_RMI_HOST, "localhost");  
  94.         int rmiPort = cfg.getIntProperty(PROP_SCHED_RMI_PORT, 1099);  
  95.         int rmiServerPort = cfg.getIntProperty(PROP_SCHED_RMI_SERVER_PORT, -1);  
  96.         String rmiCreateRegistry = cfg.getStringProperty(  
  97.                 PROP_SCHED_RMI_CREATE_REGISTRY,  
  98.                 QuartzSchedulerResources.CREATE_REGISTRY_NEVER);  
  99.         String rmiBindName = cfg.getStringProperty(PROP_SCHED_RMI_BIND_NAME);  
  100.   
  101.         if (jmxProxy && rmiProxy) {  
  102.             throw new SchedulerConfigException("Cannot proxy both RMI and JMX.");  
  103.         }  
  104.           
  105.         Properties schedCtxtProps = cfg.getPropertyGroup(PROP_SCHED_CONTEXT_PREFIX, true);  
  106.   
  107.         // If Proxying to remote scheduler, short-circuit here...  
  108.         // ~~~~~~~~~~~~~~~~~~  
  109.         if (rmiProxy) {  
  110.   
  111.             if (autoId) {  
  112.                 schedInstId = DEFAULT_INSTANCE_ID;  
  113.             }  
  114.   
  115.             String uid = (rmiBindName == null) ? QuartzSchedulerResources.getUniqueIdentifier(  
  116.                     schedName, schedInstId) : rmiBindName;  
  117.   
  118.             RemoteScheduler remoteScheduler = new RemoteScheduler(uid, rmiHost, rmiPort);  
  119.   
  120.             schedRep.bind(remoteScheduler);  
  121.   
  122.             return remoteScheduler;  
  123.         }  
  124.   
  125.   
  126.         // Create class load helper  
  127.         ClassLoadHelper loadHelper = null;  
  128.         try {  
  129.             loadHelper = (ClassLoadHelper) loadClass(classLoadHelperClass)  
  130.                     .newInstance();  
  131.         } catch (Exception e) {  
  132.             throw new SchedulerConfigException(  
  133.                     "Unable to instantiate class load helper class: "  
  134.                             + e.getMessage(), e);  
  135.         }  
  136.         loadHelper.initialize();  
  137.   
  138.         // If Proxying to remote JMX scheduler, short-circuit here...  
  139.         // ~~~~~~~~~~~~~~~~~~  
  140.         if (jmxProxy) {  
  141.             if (autoId) {  
  142.                 schedInstId = DEFAULT_INSTANCE_ID;  
  143.             }  
  144.   
  145.             if (jmxProxyClass == null) {  
  146.                 throw new SchedulerConfigException("No JMX Proxy Scheduler class provided");  
  147.             }  
  148.   
  149.             RemoteMBeanScheduler jmxScheduler = null;  
  150.             try {  
  151.                 jmxScheduler = (RemoteMBeanScheduler)loadHelper.loadClass(jmxProxyClass)  
  152.                         .newInstance();  
  153.             } catch (Exception e) {  
  154.                 throw new SchedulerConfigException(  
  155.                         "Unable to instantiate RemoteMBeanScheduler class.", e);  
  156.             }  
  157.   
  158.             if (jmxObjectName == null) {  
  159.                 jmxObjectName = QuartzSchedulerResources.generateJMXObjectName(schedName, schedInstId);  
  160.             }  
  161.   
  162.             jmxScheduler.setSchedulerObjectName(jmxObjectName);  
  163.   
  164.             tProps = cfg.getPropertyGroup(PROP_SCHED_JMX_PROXY, true);  
  165.             try {  
  166.                 setBeanProps(jmxScheduler, tProps);  
  167.             } catch (Exception e) {  
  168.                 initException = new SchedulerException("RemoteMBeanScheduler class '"  
  169.                         + jmxProxyClass + "' props could not be configured.", e);  
  170.                 throw initException;  
  171.             }  
  172.   
  173.             jmxScheduler.initialize();  
  174.   
  175.             schedRep.bind(jmxScheduler);  
  176.   
  177.             return jmxScheduler;  
  178.         }  
  179.   
  180.           
  181.         JobFactory jobFactory = null;  
  182.         if(jobFactoryClass != null) {  
  183.             try {  
  184.                 jobFactory = (JobFactory) loadHelper.loadClass(jobFactoryClass)  
  185.                         .newInstance();  
  186.             } catch (Exception e) {  
  187.                 throw new SchedulerConfigException(  
  188.                         "Unable to instantiate JobFactory class: "  
  189.                                 + e.getMessage(), e);  
  190.             }  
  191.   
  192.             tProps = cfg.getPropertyGroup(PROP_SCHED_JOB_FACTORY_PREFIX, true);  
  193.             try {  
  194.                 setBeanProps(jobFactory, tProps);  
  195.             } catch (Exception e) {  
  196.                 initException = new SchedulerException("JobFactory class '"  
  197.                         + jobFactoryClass + "' props could not be configured.", e);  
  198.                 throw initException;  
  199.             }  
  200.         }  
  201.   
  202.         InstanceIdGenerator instanceIdGenerator = null;  
  203.         if(instanceIdGeneratorClass != null) {  
  204.             try {  
  205.                 instanceIdGenerator = (InstanceIdGenerator) loadHelper.loadClass(instanceIdGeneratorClass)  
  206.                     .newInstance();  
  207.             } catch (Exception e) {  
  208.                 throw new SchedulerConfigException(  
  209.                         "Unable to instantiate InstanceIdGenerator class: "  
  210.                         + e.getMessage(), e);  
  211.             }  
  212.   
  213.             tProps = cfg.getPropertyGroup(PROP_SCHED_INSTANCE_ID_GENERATOR_PREFIX, true);  
  214.             try {  
  215.                 setBeanProps(instanceIdGenerator, tProps);  
  216.             } catch (Exception e) {  
  217.                 initException = new SchedulerException("InstanceIdGenerator class '"  
  218.                         + instanceIdGeneratorClass + "' props could not be configured.", e);  
  219.                 throw initException;  
  220.             }  
  221.         }  
  222.   
  223.         // Get ThreadPool Properties  
  224.         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
  225.   
  226.         String tpClass = cfg.getStringProperty(PROP_THREAD_POOL_CLASS, SimpleThreadPool.class.getName());  
  227.   
  228.         if (tpClass == null) {  
  229.             initException = new SchedulerException(  
  230.                     "ThreadPool class not specified. ");  
  231.             throw initException;  
  232.         }  
  233.   
  234.         try {  
  235.             //得到ThreadPool  
  236.             tp = (ThreadPool) loadHelper.loadClass(tpClass).newInstance();  
  237.         } catch (Exception e) {  
  238.             initException = new SchedulerException("ThreadPool class '"  
  239.                     + tpClass + "' could not be instantiated.", e);  
  240.             throw initException;  
  241.         }  
  242.         tProps = cfg.getPropertyGroup(PROP_THREAD_POOL_PREFIX, true);  
  243.         try {  
  244.             setBeanProps(tp, tProps);  
  245.         } catch (Exception e) {  
  246.             initException = new SchedulerException("ThreadPool class '"  
  247.                     + tpClass + "' props could not be configured.", e);  
  248.             throw initException;  
  249.         }  
  250.   
  251.         // Get JobStore Properties  
  252.         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
  253.   
  254.         String jsClass = cfg.getStringProperty(PROP_JOB_STORE_CLASS,  
  255.                 RAMJobStore.class.getName());  
  256.   
  257.         if (jsClass == null) {  
  258.             initException = new SchedulerException(  
  259.                     "JobStore class not specified. ");  
  260.             throw initException;  
  261.         }  
  262.   
  263.         try {  
  264.             js = (JobStore) loadHelper.loadClass(jsClass).newInstance();  
  265.         } catch (Exception e) {  
  266.             initException = new SchedulerException("JobStore class '" + jsClass  
  267.                     + "' could not be instantiated.", e);  
  268.             throw initException;  
  269.         }  
  270.   
  271.         SchedulerDetailsSetter.setDetails(js, schedName, schedInstId);  
  272.   
  273.         tProps = cfg.getPropertyGroup(PROP_JOB_STORE_PREFIX, truenew String[] {PROP_JOB_STORE_LOCK_HANDLER_PREFIX});  
  274.         try {  
  275.             setBeanProps(js, tProps);  
  276.         } catch (Exception e) {  
  277.             initException = new SchedulerException("JobStore class '" + jsClass  
  278.                     + "' props could not be configured.", e);  
  279.             throw initException;  
  280.         }  
  281.   
  282.         if (js instanceof JobStoreSupport) {  
  283.             // Install custom lock handler (Semaphore)  
  284.             String lockHandlerClass = cfg.getStringProperty(PROP_JOB_STORE_LOCK_HANDLER_CLASS);  
  285.             if (lockHandlerClass != null) {  
  286.                 try {  
  287.                     Semaphore lockHandler = (Semaphore)loadHelper.loadClass(lockHandlerClass).newInstance();  
  288.   
  289.                     tProps = cfg.getPropertyGroup(PROP_JOB_STORE_LOCK_HANDLER_PREFIX, true);  
  290.   
  291.                     // If this lock handler requires the table prefix, add it to its properties.  
  292.                     if (lockHandler instanceof TablePrefixAware) {  
  293.                         tProps.setProperty(  
  294.                                 PROP_TABLE_PREFIX, ((JobStoreSupport)js).getTablePrefix());  
  295.                         tProps.setProperty(  
  296.                                 PROP_SCHED_NAME, schedName);  
  297.                     }  
  298.   
  299.                     try {  
  300.                         setBeanProps(lockHandler, tProps);  
  301.                     } catch (Exception e) {  
  302.                         initException = new SchedulerException("JobStore LockHandler class '" + lockHandlerClass  
  303.                                 + "' props could not be configured.", e);  
  304.                         throw initException;  
  305.                     }  
  306.   
  307.                     ((JobStoreSupport)js).setLockHandler(lockHandler);  
  308.                     getLog().info("Using custom data access locking (synchronization): " + lockHandlerClass);  
  309.                 } catch (Exception e) {  
  310.                     initException = new SchedulerException("JobStore LockHandler class '" + lockHandlerClass  
  311.                             + "' could not be instantiated.", e);  
  312.                     throw initException;  
  313.                 }  
  314.             }  
  315.         }  
  316.   
  317.         // Set up any DataSources  
  318.         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
  319.   
  320.         String[] dsNames = cfg.getPropertyGroups(PROP_DATASOURCE_PREFIX);  
  321.         for (int i = 0; i < dsNames.length; i++) {  
  322.             PropertiesParser pp = new PropertiesParser(cfg.getPropertyGroup(  
  323.                     PROP_DATASOURCE_PREFIX + "." + dsNames[i], true));  
  324.   
  325.             String cpClass = pp.getStringProperty(PROP_CONNECTION_PROVIDER_CLASS, null);  
  326.   
  327.             // custom connectionProvider...  
  328.             if(cpClass != null) {  
  329.                 ConnectionProvider cp = null;  
  330.                 try {  
  331.                     cp = (ConnectionProvider) loadHelper.loadClass(cpClass).newInstance();  
  332.                 } catch (Exception e) {  
  333.                     initException = new SchedulerException("ConnectionProvider class '" + cpClass  
  334.                             + "' could not be instantiated.", e);  
  335.                     throw initException;  
  336.                 }  
  337.   
  338.                 try {  
  339.                     // remove the class name, so it isn't attempted to be set  
  340.                     pp.getUnderlyingProperties().remove(  
  341.                             PROP_CONNECTION_PROVIDER_CLASS);  
  342.   
  343.                     setBeanProps(cp, pp.getUnderlyingProperties());  
  344.                 } catch (Exception e) {  
  345.                     initException = new SchedulerException("ConnectionProvider class '" + cpClass  
  346.                             + "' props could not be configured.", e);  
  347.                     throw initException;  
  348.                 }  
  349.   
  350.                 dbMgr = DBConnectionManager.getInstance();  
  351.                 dbMgr.addConnectionProvider(dsNames[i], cp);  
  352.             } else {  
  353.                 String dsJndi = pp.getStringProperty(PROP_DATASOURCE_JNDI_URL, null);  
  354.   
  355.                 if (dsJndi != null) {  
  356.                     boolean dsAlwaysLookup = pp.getBooleanProperty(  
  357.                             PROP_DATASOURCE_JNDI_ALWAYS_LOOKUP);  
  358.                     String dsJndiInitial = pp.getStringProperty(  
  359.                             PROP_DATASOURCE_JNDI_INITIAL);  
  360.                     String dsJndiProvider = pp.getStringProperty(  
  361.                             PROP_DATASOURCE_JNDI_PROVDER);  
  362.                     String dsJndiPrincipal = pp.getStringProperty(  
  363.                             PROP_DATASOURCE_JNDI_PRINCIPAL);  
  364.                     String dsJndiCredentials = pp.getStringProperty(  
  365.                             PROP_DATASOURCE_JNDI_CREDENTIALS);  
  366.                     Properties props = null;  
  367.                     if (null != dsJndiInitial || null != dsJndiProvider  
  368.                             || null != dsJndiPrincipal || null != dsJndiCredentials) {  
  369.                         props = new Properties();  
  370.                         if (dsJndiInitial != null) {  
  371.                             props.put(PROP_DATASOURCE_JNDI_INITIAL,  
  372.                                     dsJndiInitial);  
  373.                         }  
  374.                         if (dsJndiProvider != null) {  
  375.                             props.put(PROP_DATASOURCE_JNDI_PROVDER,  
  376.                                     dsJndiProvider);  
  377.                         }  
  378.                         if (dsJndiPrincipal != null) {  
  379.                             props.put(PROP_DATASOURCE_JNDI_PRINCIPAL,  
  380.                                     dsJndiPrincipal);  
  381.                         }  
  382.                         if (dsJndiCredentials != null) {  
  383.                             props.put(PROP_DATASOURCE_JNDI_CREDENTIALS,  
  384.                                     dsJndiCredentials);  
  385.                         }  
  386.                     }  
  387.                     JNDIConnectionProvider cp = new JNDIConnectionProvider(dsJndi,  
  388.                             props, dsAlwaysLookup);  
  389.                     dbMgr = DBConnectionManager.getInstance();  
  390.                     dbMgr.addConnectionProvider(dsNames[i], cp);  
  391.                 } else {  
  392.                     String dsDriver = pp.getStringProperty(PROP_DATASOURCE_DRIVER);  
  393.                     String dsURL = pp.getStringProperty(PROP_DATASOURCE_URL);  
  394.                     String dsUser = pp.getStringProperty(PROP_DATASOURCE_USER, "");  
  395.                     String dsPass = pp.getStringProperty(PROP_DATASOURCE_PASSWORD, "");  
  396.                     int dsCnt = pp.getIntProperty(PROP_DATASOURCE_MAX_CONNECTIONS, 10);  
  397.                     String dsValidation = pp.getStringProperty(PROP_DATASOURCE_VALIDATION_QUERY);  
  398.   
  399.                     if (dsDriver == null) {  
  400.                         initException = new SchedulerException(  
  401.                                 "Driver not specified for DataSource: "  
  402.                                         + dsNames[i]);  
  403.                         throw initException;  
  404.                     }  
  405.                     if (dsURL == null) {  
  406.                         initException = new SchedulerException(  
  407.                                 "DB URL not specified for DataSource: "  
  408.                                         + dsNames[i]);  
  409.                         throw initException;  
  410.                     }  
  411.                     try {  
  412.                         PoolingConnectionProvider cp = new PoolingConnectionProvider(  
  413.                                 dsDriver, dsURL, dsUser, dsPass, dsCnt,  
  414.                                 dsValidation);  
  415.                         dbMgr = DBConnectionManager.getInstance();  
  416.                         dbMgr.addConnectionProvider(dsNames[i], cp);  
  417.                     } catch (SQLException sqle) {  
  418.                         initException = new SchedulerException(  
  419.                                 "Could not initialize DataSource: " + dsNames[i],  
  420.                                 sqle);  
  421.                         throw initException;  
  422.                     }  
  423.                 }  
  424.   
  425.             }  
  426.   
  427.         }  
  428.   
  429.         // Set up any SchedulerPlugins  
  430.         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
  431.   
  432.         String[] pluginNames = cfg.getPropertyGroups(PROP_PLUGIN_PREFIX);  
  433.         SchedulerPlugin[] plugins = new SchedulerPlugin[pluginNames.length];  
  434.         for (int i = 0; i < pluginNames.length; i++) {  
  435.             Properties pp = cfg.getPropertyGroup(PROP_PLUGIN_PREFIX + "."  
  436.                     + pluginNames[i], true);  
  437.   
  438.             String plugInClass = pp.getProperty(PROP_PLUGIN_CLASS, null);  
  439.   
  440.             if (plugInClass == null) {  
  441.                 initException = new SchedulerException(  
  442.                         "SchedulerPlugin class not specified for plugin '"  
  443.                                 + pluginNames[i] + "'");  
  444.                 throw initException;  
  445.             }  
  446.             SchedulerPlugin plugin = null;  
  447.             try {  
  448.                 plugin = (SchedulerPlugin)  
  449.                         loadHelper.loadClass(plugInClass).newInstance();  
  450.             } catch (Exception e) {  
  451.                 initException = new SchedulerException(  
  452.                         "SchedulerPlugin class '" + plugInClass  
  453.                                 + "' could not be instantiated.", e);  
  454.                 throw initException;  
  455.             }  
  456.             try {  
  457.                 setBeanProps(plugin, pp);  
  458.             } catch (Exception e) {  
  459.                 initException = new SchedulerException(  
  460.                         "JobStore SchedulerPlugin '" + plugInClass  
  461.                                 + "' props could not be configured.", e);  
  462.                 throw initException;  
  463.             }  
  464.   
  465.             plugins[i] = plugin;  
  466.         }  
  467.   
  468.         // Set up any JobListeners  
  469.         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
  470.   
  471.         Class[] strArg = new Class[] { String.class };  
  472.         String[] jobListenerNames = cfg.getPropertyGroups(PROP_JOB_LISTENER_PREFIX);  
  473.         JobListener[] jobListeners = new JobListener[jobListenerNames.length];  
  474.         for (int i = 0; i < jobListenerNames.length; i++) {  
  475.             Properties lp = cfg.getPropertyGroup(PROP_JOB_LISTENER_PREFIX + "."  
  476.                     + jobListenerNames[i], true);  
  477.   
  478.             String listenerClass = lp.getProperty(PROP_LISTENER_CLASS, null);  
  479.   
  480.             if (listenerClass == null) {  
  481.                 initException = new SchedulerException(  
  482.                         "JobListener class not specified for listener '"  
  483.                                 + jobListenerNames[i] + "'");  
  484.                 throw initException;  
  485.             }  
  486.             JobListener listener = null;  
  487.             try {  
  488.                 listener = (JobListener)  
  489.                        loadHelper.loadClass(listenerClass).newInstance();  
  490.             } catch (Exception e) {  
  491.                 initException = new SchedulerException(  
  492.                         "JobListener class '" + listenerClass  
  493.                                 + "' could not be instantiated.", e);  
  494.                 throw initException;  
  495.             }  
  496.             try {  
  497.                 Method nameSetter = listener.getClass().getMethod("setName", strArg);  
  498.                 if(nameSetter != null) {  
  499.                     nameSetter.invoke(listener, new Object[] {jobListenerNames[i] } );  
  500.                 }  
  501.                 setBeanProps(listener, lp);  
  502.             } catch (Exception e) {  
  503.                 initException = new SchedulerException(  
  504.                         "JobListener '" + listenerClass  
  505.                                 + "' props could not be configured.", e);  
  506.                 throw initException;  
  507.             }  
  508.             jobListeners[i] = listener;  
  509.         }  
  510.   
  511.         // Set up any TriggerListeners  
  512.         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
  513.   
  514.         String[] triggerListenerNames = cfg.getPropertyGroups(PROP_TRIGGER_LISTENER_PREFIX);  
  515.         TriggerListener[] triggerListeners = new TriggerListener[triggerListenerNames.length];  
  516.         for (int i = 0; i < triggerListenerNames.length; i++) {  
  517.             Properties lp = cfg.getPropertyGroup(PROP_TRIGGER_LISTENER_PREFIX + "."  
  518.                     + triggerListenerNames[i], true);  
  519.   
  520.             String listenerClass = lp.getProperty(PROP_LISTENER_CLASS, null);  
  521.   
  522.             if (listenerClass == null) {  
  523.                 initException = new SchedulerException(  
  524.                         "TriggerListener class not specified for listener '"  
  525.                                 + triggerListenerNames[i] + "'");  
  526.                 throw initException;  
  527.             }  
  528.             TriggerListener listener = null;  
  529.             try {  
  530.                 listener = (TriggerListener)  
  531.                        loadHelper.loadClass(listenerClass).newInstance();  
  532.             } catch (Exception e) {  
  533.                 initException = new SchedulerException(  
  534.                         "TriggerListener class '" + listenerClass  
  535.                                 + "' could not be instantiated.", e);  
  536.                 throw initException;  
  537.             }  
  538.             try {  
  539.                 Method nameSetter = listener.getClass().getMethod("setName", strArg);  
  540.                 if(nameSetter != null) {  
  541.                     nameSetter.invoke(listener, new Object[] {triggerListenerNames[i] } );  
  542.                 }  
  543.                 setBeanProps(listener, lp);  
  544.             } catch (Exception e) {  
  545.                 initException = new SchedulerException(  
  546.                         "TriggerListener '" + listenerClass  
  547.                                 + "' props could not be configured.", e);  
  548.                 throw initException;  
  549.             }  
  550.             triggerListeners[i] = listener;  
  551.         }  
  552.   
  553.         boolean tpInited = false;  
  554.         boolean qsInited = false;  
  555.   
  556.   
  557.         // Get ThreadExecutor Properties  
  558.         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
  559.   
  560.         String threadExecutorClass = cfg.getStringProperty(PROP_THREAD_EXECUTOR_CLASS);  
  561.         if (threadExecutorClass != null) {  
  562.             tProps = cfg.getPropertyGroup(PROP_THREAD_EXECUTOR, true);  
  563.             try {  
  564.                 threadExecutor = (ThreadExecutor) loadHelper.loadClass(threadExecutorClass).newInstance();  
  565.                 log.info("Using custom implementation for ThreadExecutor: " + threadExecutorClass);  
  566.   
  567.                 setBeanProps(threadExecutor, tProps);  
  568.             } catch (Exception e) {  
  569.                 initException = new SchedulerException(  
  570.                         "ThreadExecutor class '" + threadExecutorClass + "' could not be instantiated.", e);  
  571.                 throw initException;  
  572.             }  
  573.         } else {  
  574.             log.info("Using default implementation for ThreadExecutor");  
  575.             threadExecutor = new DefaultThreadExecutor();  
  576.         }  
  577.   
  578.   
  579.         // Fire everything up  
  580.         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
  581.         try {  
  582.                   
  583.       
  584.             JobRunShellFactory jrsf = null// Create correct run-shell factory...  
  585.       
  586.             if (userTXLocation != null) {  
  587.                 UserTransactionHelper.setUserTxLocation(userTXLocation);  
  588.             }  
  589.       
  590.             if (wrapJobInTx) {  
  591.                 jrsf = new JTAJobRunShellFactory();  
  592.             } else {  
  593.                 jrsf = new JTAAnnotationAwareJobRunShellFactory();  
  594.             }  
  595.       
  596.             if (autoId) {  
  597.                 try {  
  598.                   schedInstId = DEFAULT_INSTANCE_ID;  
  599.                   if (js.isClustered()) {  
  600.                       schedInstId = instanceIdGenerator.generateInstanceId();  
  601.                   }  
  602.                 } catch (Exception e) {  
  603.                     getLog().error("Couldn't generate instance Id!", e);  
  604.                     throw new IllegalStateException("Cannot run without an instance id.");  
  605.                 }  
  606.             }  
  607.   
  608.             if (js.getClass().getName().startsWith("org.terracotta.quartz")) {  
  609.                 try {  
  610.                     String uuid = (String) js.getClass().getMethod("getUUID").invoke(js);  
  611.                     if(schedInstId.equals(DEFAULT_INSTANCE_ID)) {  
  612.                         schedInstId = "TERRACOTTA_CLUSTERED,node=" + uuid;  
  613.                         if (jmxObjectName == null) {  
  614.                             jmxObjectName = QuartzSchedulerResources.generateJMXObjectName(schedName, schedInstId);  
  615.                         }  
  616.                     } else if(jmxObjectName == null) {  
  617.                         jmxObjectName = QuartzSchedulerResources.generateJMXObjectName(schedName, schedInstId + ",node=" + uuid);  
  618.                     }  
  619.                 } catch(Exception e) {  
  620.                     throw new RuntimeException("Problem obtaining node id from TerracottaJobStore.", e);  
  621.                 }  
  622.   
  623.                 if(null == cfg.getStringProperty(PROP_SCHED_JMX_EXPORT)) {  
  624.                     jmxExport = true;  
  625.                 }  
  626.             }  
  627.               
  628.             if (js instanceof JobStoreSupport) {  
  629.                 JobStoreSupport jjs = (JobStoreSupport)js;  
  630.                 jjs.setDbRetryInterval(dbFailureRetry);  
  631.                 if(threadsInheritInitalizersClassLoader)  
  632.                     jjs.setThreadsInheritInitializersClassLoadContext(threadsInheritInitalizersClassLoader);  
  633.             }  
  634.       
  635.             QuartzSchedulerResources rsrcs = new QuartzSchedulerResources();  
  636.             rsrcs.setName(schedName);  
  637.             rsrcs.setThreadName(threadName);  
  638.             rsrcs.setInstanceId(schedInstId);  
  639.             rsrcs.setJobRunShellFactory(jrsf);  
  640.             rsrcs.setMakeSchedulerThreadDaemon(makeSchedulerThreadDaemon);  
  641.             rsrcs.setThreadsInheritInitializersClassLoadContext(threadsInheritInitalizersClassLoader);  
  642.             rsrcs.setRunUpdateCheck(!skipUpdateCheck);  
  643.             rsrcs.setBatchTimeWindow(batchTimeWindow);  
  644.             rsrcs.setMaxBatchSize(maxBatchSize);  
  645.             rsrcs.setInterruptJobsOnShutdown(interruptJobsOnShutdown);  
  646.             rsrcs.setInterruptJobsOnShutdownWithWait(interruptJobsOnShutdownWithWait);  
  647.             rsrcs.setJMXExport(jmxExport);  
  648.             rsrcs.setJMXObjectName(jmxObjectName);  
  649.       
  650.             if (rmiExport) {  
  651.                 rsrcs.setRMIRegistryHost(rmiHost);  
  652.                 rsrcs.setRMIRegistryPort(rmiPort);  
  653.                 rsrcs.setRMIServerPort(rmiServerPort);  
  654.                 rsrcs.setRMICreateRegistryStrategy(rmiCreateRegistry);  
  655.                 rsrcs.setRMIBindName(rmiBindName);  
  656.             }  
  657.       
  658.             SchedulerDetailsSetter.setDetails(tp, schedName, schedInstId);  
  659.       
  660.             rsrcs.setThreadExecutor(threadExecutor);  
  661.             threadExecutor.initialize();  
  662.   
  663.             rsrcs.setThreadPool(tp);  
  664.             if(tp instanceof SimpleThreadPool) {  
  665.                 ((SimpleThreadPool)tp).setThreadNamePrefix(schedName + "_Worker");  
  666.                 if(threadsInheritInitalizersClassLoader)  
  667.                     ((SimpleThreadPool)tp).setThreadsInheritContextClassLoaderOfInitializingThread(threadsInheritInitalizersClassLoader);  
  668.             }  
  669.             //ThreadPool初始化  
  670.             tp.initialize();  
  671.             tpInited = true;  
  672.       
  673.             rsrcs.setJobStore(js);  
  674.       
  675.             // add plugins  
  676.             for (int i = 0; i < plugins.length; i++) {  
  677.                 rsrcs.addSchedulerPlugin(plugins[i]);  
  678.             }  
  679.             //得到QuartzSchedulerThread 默认paused=true  
  680.             qs = new QuartzScheduler(rsrcs, idleWaitTime, dbFailureRetry);  
  681.             qsInited = true;  
  682.       
  683.             // Create Scheduler ref...  
  684.             Scheduler scheduler = instantiate(rsrcs, qs);  
  685.       
  686.             // set job factory if specified  
  687.             if(jobFactory != null) {  
  688.                 qs.setJobFactory(jobFactory);  
  689.             }  
  690.       
  691.             // Initialize plugins now that we have a Scheduler instance.  
  692.             for (int i = 0; i < plugins.length; i++) {  
  693.                 plugins[i].initialize(pluginNames[i], scheduler);  
  694.             }  
  695.       
  696.             // add listeners  
  697.             for (int i = 0; i < jobListeners.length; i++) {  
  698.                 qs.getListenerManager().addJobListener(jobListeners[i], EverythingMatcher.allJobs());  
  699.             }  
  700.             for (int i = 0; i < triggerListeners.length; i++) {  
  701.                 qs.getListenerManager().addTriggerListener(triggerListeners[i], EverythingMatcher.allTriggers());  
  702.             }  
  703.       
  704.             // set scheduler context data...  
  705.             for(Object key: schedCtxtProps.keySet()) {  
  706.                 String val = schedCtxtProps.getProperty((String) key);  
  707.       
  708.                 scheduler.getContext().put(key, val);  
  709.             }  
  710.       
  711.             // fire up job store, and runshell factory  
  712.       
  713.             js.setInstanceId(schedInstId);  
  714.             js.setInstanceName(schedName);  
  715.             js.initialize(loadHelper, qs.getSchedulerSignaler());  
  716.             js.setThreadPoolSize(tp.getPoolSize());  
  717.   
  718.             jrsf.initialize(scheduler);  
  719.               
  720.             qs.initialize();  
  721.       
  722.             getLog().info(  
  723.                     "Quartz scheduler '" + scheduler.getSchedulerName()  
  724.                             + "' initialized from " + propSrc);  
  725.       
  726.             getLog().info("Quartz scheduler version: " + qs.getVersion());  
  727.       
  728.             // prevents the repository from being garbage collected  
  729.             qs.addNoGCObject(schedRep);  
  730.             // prevents the db manager from being garbage collected  
  731.             if (dbMgr != null) {  
  732.                 qs.addNoGCObject(dbMgr);  
  733.             }  
  734.       
  735.             schedRep.bind(scheduler);  
  736.             return scheduler;  
  737.         }  
  738.         catch(SchedulerException e) {  
  739.             if(qsInited)  
  740.                 qs.shutdown(false);  
  741.             else if(tpInited)  
  742.                 tp.shutdown(false);  
  743.             throw e;  
  744.         }  
  745.         catch(RuntimeException re) {  
  746.             if(qsInited)  
  747.                 qs.shutdown(false);  
  748.             else if(tpInited)  
  749.                 tp.shutdown(false);  
  750.             throw re;  
  751.         }  
  752.         catch(Error re) {  
  753.             if(qsInited)  
  754.                 qs.shutdown(false);  
  755.             else if(tpInited)  
  756.                 tp.shutdown(false);  
  757.             throw re;  
  758.         }  
  759.     }  

 

 3.2在QuartzSchedulerThread线程中循环通过JobStore取得List后通过ThreadPool执行JobRunShell。

QuartzSchedulerThread:

 

Java代码
  1. public void run() {  
  2.         boolean lastAcquireFailed = false;  
  3.   
  4.         while (!halted.get()) {  
  5.             try {  
  6.                 // check if we're supposed to pause...  
  7.                 synchronized (sigLock) {  
  8.                     while (paused && !halted.get()) {  
  9.                         try {  
  10.                             // wait until togglePause(false) is called...  
  11.                             sigLock.wait(1000L);  
  12.                         } catch (InterruptedException ignore) {  
  13.                         }  
  14.                     }  
  15.   
  16.                     if (halted.get()) {  
  17.                         break;  
  18.                     }  
  19.                 }  
  20.   
  21.                 int availThreadCount = qsRsrcs.getThreadPool().blockForAvailableThreads();  
  22.                 if(availThreadCount > 0) { // will always be true, due to semantics of blockForAvailableThreads...  
  23.   
  24.                     List triggers = null;  
  25.   
  26.                     long now = System.currentTimeMillis();  
  27.   
  28.                     clearSignaledSchedulingChange();  
  29.                     try {  
  30.                         //通过JobStore取得List  
  31.                         triggers = qsRsrcs.getJobStore().acquireNextTriggers(  
  32.                                 now + idleWaitTime, Math.min(availThreadCount, qsRsrcs.getMaxBatchSize()), qsRsrcs.getBatchTimeWindow());  
  33.                         lastAcquireFailed = false;  
  34.                         if (log.isDebugEnabled())   
  35.                             log.debug("batch acquisition of " + (triggers == null ? 0 : triggers.size()) + " triggers");  
  36.                     } catch (JobPersistenceException jpe) {  
  37.                         if(!lastAcquireFailed) {  
  38.                             qs.notifySchedulerListenersError(  
  39.                                 "An error occurred while scanning for the next triggers to fire.",  
  40.                                 jpe);  
  41.                         }  
  42.                         lastAcquireFailed = true;  
  43.                     } catch (RuntimeException e) {  
  44.                         if(!lastAcquireFailed) {  
  45.                             getLog().error("quartzSchedulerThreadLoop: RuntimeException "  
  46.                                     +e.getMessage(), e);  
  47.                         }  
  48.                         lastAcquireFailed = true;  
  49.                     }  
  50.   
  51.                     if (triggers != null && !triggers.isEmpty()) {  
  52.   
  53.                         now = System.currentTimeMillis();  
  54.                         long triggerTime = triggers.get(0).getNextFireTime().getTime();  
  55.                         long timeUntilTrigger = triggerTime - now;  
  56.                         while(timeUntilTrigger > 2) {  
  57.                             synchronized (sigLock) {  
  58.                                 if (halted.get()) {  
  59.                                     break;  
  60.                                 }  
  61.                                 if (!isCandidateNewTimeEarlierWithinReason(triggerTime, false)) {  
  62.                                     try {  
  63.                                         // we could have blocked a long while  
  64.                                         // on 'synchronize', so we must recompute  
  65.                                         now = System.currentTimeMillis();  
  66.                                         timeUntilTrigger = triggerTime - now;  
  67.                                         if(timeUntilTrigger >= 1)  
  68.                                             sigLock.wait(timeUntilTrigger);  
  69.                                     } catch (InterruptedException ignore) {  
  70.                                     }  
  71.                                 }  
  72.                             }  
  73.                             if(releaseIfScheduleChangedSignificantly(triggers, triggerTime)) {  
  74.                                 break;  
  75.                             }  
  76.                             now = System.currentTimeMillis();  
  77.                             timeUntilTrigger = triggerTime - now;  
  78.                         }  
  79.   
  80.                         // this happens if releaseIfScheduleChangedSignificantly decided to release triggers  
  81.                         if(triggers.isEmpty())  
  82.                             continue;  
  83.   
  84.                         // set triggers to 'executing'  
  85.                         List bndles = new ArrayList();  
  86.   
  87.                         boolean goAhead = true;  
  88.                         synchronized(sigLock) {  
  89.                             goAhead = !halted.get();  
  90.                         }  
  91.                         if(goAhead) {  
  92.                             try {  
  93.                                 //告知JobStore开始执行trigger,内存则移除,表则更新qrtz_triggers信息  
  94.                                 List res = qsRsrcs.getJobStore().triggersFired(triggers);  
  95.                                 if(res != null)  
  96.                                     bndles = res;  
  97.                             } catch (SchedulerException se) {  
  98.                                 qs.notifySchedulerListenersError(  
  99.                                         "An error occurred while firing triggers '"  
  100.                                                 + triggers + "'", se);  
  101.                             }  
  102.   
  103.                         }  
  104.   
  105.                         for (int i = 0; i < bndles.size(); i++) {  
  106.                             TriggerFiredResult result =  bndles.get(i);  
  107.                             TriggerFiredBundle bndle =  result.getTriggerFiredBundle();  
  108.                             Exception exception = result.getException();  
  109.   
  110.                             if (exception instanceof RuntimeException) {  
  111.                                 getLog().error(  
  112.                                     "RuntimeException while firing trigger " +  
  113.                                     triggers.get(i), exception);  
  114.                                 // db connection must have failed... keep  
  115.                                 // retrying until it's up...  
  116.                                 releaseTriggerRetryLoop(triggers.get(i));  
  117.                                 continue;  
  118.                             }  
  119.   
  120.                             // it's possible to get 'null' if the triggers was paused,  
  121.                             // blocked, or other similar occurrences that prevent it being  
  122.                             // fired at this time...  or if the scheduler was shutdown (halted)  
  123.                             if (bndle == null) {  
  124.                                 try {  
  125.                                     qsRsrcs.getJobStore().releaseAcquiredTrigger(triggers.get(i));  
  126.                                 } catch (SchedulerException se) {  
  127.                                     qs.notifySchedulerListenersError(  
  128.                                             "An error occurred while releasing triggers '"  
  129.                                                     + triggers.get(i).getKey() + "'", se);  
  130.                                     // db connection must have failed... keep retrying  
  131.                                     // until it's up...  
  132.                                     releaseTriggerRetryLoop(triggers.get(i));  
  133.                                 }  
  134.                                 continue;  
  135.                             }  
  136.   
  137.   
  138.                             // TODO: improvements:  
  139.                             //  
  140.                             // 2- make sure we can get a job runshell before firing triggers, or  
  141.                             //   don't let that throw an exception (right now it never does,  
  142.                             //   but the signature says it can).  
  143.                             // 3- acquire more triggers at a time (based on num threads available?)  
  144.   
  145.                             //得到JobRunShell  
  146.                             JobRunShell shell = null;  
  147.                             try {  
  148.                                 shell = qsRsrcs.getJobRunShellFactory().createJobRunShell(bndle);  
  149.                                 //初始化JobRunShell      
  150.                                 shell.initialize(qs);  
  151.                             } catch (SchedulerException se) {  
  152.                                 try {  
  153.                                     qsRsrcs.getJobStore().triggeredJobComplete(  
  154.                                             triggers.get(i), bndle.getJobDetail(), CompletedExecutionInstruction.SET_ALL_JOB_TRIGGERS_ERROR);  
  155.                                 } catch (SchedulerException se2) {  
  156.                                     qs.notifySchedulerListenersError(  
  157.                                             "An error occurred while placing job's triggers in error state '"  
  158.                                                     + triggers.get(i).getKey() + "'", se2);  
  159.                                     // db connection must have failed... keep retrying  
  160.                                     // until it's up...  
  161.                                     errorTriggerRetryLoop(bndle);  
  162.                                 }  
  163.                                 continue;  
  164.                             }  
  165.                             //通过ThreadPool执行JobRunShell  
  166.                             if (qsRsrcs.getThreadPool().runInThread(shell) == false) {  
  167.                                 try {  
  168.                                     // this case should never happen, as it is indicative of the  
  169.                                     // scheduler being shutdown or a bug in the thread pool or  
  170.                                     // a thread pool being used concurrently - which the docs  
  171.                                     // say not to do...  
  172.                                     getLog().error("ThreadPool.runInThread() return false!");  
  173.                                     qsRsrcs.getJobStore().triggeredJobComplete(  
  174.                                             triggers.get(i), bndle.getJobDetail(), CompletedExecutionInstruction.SET_ALL_JOB_TRIGGERS_ERROR);  
  175.                                 } catch (SchedulerException se2) {  
  176.                                     qs.notifySchedulerListenersError(  
  177.                                             "An error occurred while placing job's triggers in error state '"  
  178.                                                     + triggers.get(i).getKey() + "'", se2);  
  179.                                     // db connection must have failed... keep retrying  
  180.                                     // until it's up...  
  181.                                     releaseTriggerRetryLoop(triggers.get(i));  
  182.                                 }  
  183.                             }  
  184.   
  185.                         }  
  186.   
  187.                         continue// while (!halted)  
  188.                     }  
  189.                 } else { // if(availThreadCount > 0)  
  190.                     // should never happen, if threadPool.blockForAvailableThreads() follows contract  
  191.                     continue// while (!halted)  
  192.                 }  
  193.   
  194.                 long now = System.currentTimeMillis();  
  195.                 long waitTime = now + getRandomizedIdleWaitTime();  
  196.                 long timeUntilContinue = waitTime - now;  
  197.                 synchronized(sigLock) {  
  198.                     try {  
  199.                         sigLock.wait(timeUntilContinue);  
  200.                     } catch (InterruptedException ignore) {  
  201.                     }  
  202.                 }  
  203.   
  204.             } catch(RuntimeException re) {  
  205.                 getLog().error("Runtime error occurred in main trigger firing loop.", re);  
  206.             }  
  207.         } // while (!halted)  
  208.   
  209.         // drop references to scheduler stuff to aid garbage collection...  
  210.         qs = null;  
  211.         qsRsrcs = null;  
  212.     }  
 

 3.3JobStore得到List

  RAMJobStore取得List方法使用hashTree

Java代码
  1. public List acquireNextTriggers(long noLaterThan, int maxCount, long timeWindow) {  
  2.         synchronized (lock) {  
  3.             List result = new ArrayList();  
  4.   
  5.             while (true) {  
  6.                 TriggerWrapper tw;  
  7.   
  8.                 try {  
  9.                     tw = (TriggerWrapper) timeTriggers.first();  
  10.                     if (tw == nullreturn result;  
  11.                     timeTriggers.remove(tw);  
  12.                 } catch (java.util.NoSuchElementException nsee) {  
  13.                     return result;  
  14.                 }  
  15.   
  16.                 if (tw.trigger.getNextFireTime() == null) {  
  17.                     continue;  
  18.                 }  
  19.   
  20.                 if (applyMisfire(tw)) {  
  21.                     if (tw.trigger.getNextFireTime() != null) {  
  22.                         timeTriggers.add(tw);  
  23.                     }  
  24.                     continue;  
  25.                 }  
  26.   
  27.                 if (tw.getTrigger().getNextFireTime().getTime() > noLaterThan + timeWindow) {  
  28.                     timeTriggers.add(tw);  
  29.                     return result;  
  30.                 }  
  31.   
  32.                 tw.state = TriggerWrapper.STATE_ACQUIRED;  
  33.   
  34.                 tw.trigger.setFireInstanceId(getFiredTriggerRecordId());  
  35.                 OperableTrigger trig = (OperableTrigger) tw.trigger.clone();  
  36.                 result.add(trig);  
  37.   
  38.                 if (result.size() == maxCount)  
  39.                   return result;  
  40.             }  
  41.         }  
  42.     }  

 

 3.4JobRunShell

初始化:

Java代码
  1. public void initialize(QuartzScheduler qs)  
  2.         throws SchedulerException {  
  3.         this.qs = qs;  
  4.   
  5.         Job job = null;  
  6.         JobDetail jobDetail = firedTriggerBundle.getJobDetail();  
  7.   
  8.         try {  
  9.             job = qs.getJobFactory().newJob(firedTriggerBundle, scheduler);  
  10.         } catch (SchedulerException se) {  
  11.             qs.notifySchedulerListenersError(  
  12.                     "An error occured instantiating job to be executed. job= '"  
  13.                             + jobDetail.getKey() + "'", se);  
  14.             throw se;  
  15.         } catch (Throwable ncdfe) { // such as NoClassDefFoundError  
  16.             SchedulerException se = new SchedulerException(  
  17.                     "Problem instantiating class '"  
  18.                             + jobDetail.getJobClass().getName() + "' - ", ncdfe);  
  19.             qs.notifySchedulerListenersError(  
  20.                     "An error occured instantiating job to be executed. job= '"  
  21.                             + jobDetail.getKey() + "'", se);  
  22.             throw se;  
  23.         }  
  24.   
  25.         this.jec = new JobExecutionContextImpl(scheduler, firedTriggerBundle, job);  
  26.     }  

 run方法

Java代码
  1. public void run() {  
  2.         qs.addInternalSchedulerListener(this);  
  3.   
  4.         try {  
  5.             OperableTrigger trigger = (OperableTrigger) jec.getTrigger();  
  6.             JobDetail jobDetail = jec.getJobDetail();  
  7.   
  8.             do {  
  9.   
  10.                 JobExecutionException jobExEx = null;  
  11.                 Job job = jec.getJobInstance();  
  12.   
  13.                 try {  
  14.                     begin();  
  15.                 } catch (SchedulerException se) {  
  16.                     qs.notifySchedulerListenersError("Error executing Job ("  
  17.                             + jec.getJobDetail().getKey()  
  18.                             + ": couldn't begin execution.", se);  
  19.                     break;  
  20.                 }  
  21.   
  22.                 // notify job & trigger listeners...  
  23.                 try {  
  24.                     if (!notifyListenersBeginning(jec)) {  
  25.                         break;  
  26.                     }  
  27.                 } catch(VetoedException ve) {  
  28.                     try {  
  29.                         CompletedExecutionInstruction instCode = trigger.executionComplete(jec, null);  
  30.                         try {  
  31.                             qs.notifyJobStoreJobVetoed(trigger, jobDetail, instCode);  
  32.                         } catch(JobPersistenceException jpe) {  
  33.                             vetoedJobRetryLoop(trigger, jobDetail, instCode);  
  34.                         }  
  35.                         complete(true);  
  36.                     } catch (SchedulerException se) {  
  37.                         qs.notifySchedulerListenersError("Error during veto of Job ("  
  38.                                 + jec.getJobDetail().getKey()  
  39.                                 + ": couldn't finalize execution.", se);  
  40.                     }  
  41.                     break;  
  42.                 }  
  43.   
  44.                 long startTime = System.currentTimeMillis();  
  45.                 long endTime = startTime;  
  46.   
  47.                 // execute the job  
  48.                 try {  
  49.                     log.debug("Calling execute on job " + jobDetail.getKey());  
  50.                     job.execute(jec);  
  51.                     endTime = System.currentTimeMillis();  
  52.                 } catch (JobExecutionException jee) {  
  53.                     endTime = System.currentTimeMillis();  
  54.                     jobExEx = jee;  
  55.                     getLog().info("Job " + jobDetail.getKey() +  
  56.                             " threw a JobExecutionException: ", jobExEx);  
  57.                 } catch (Throwable e) {  
  58.                     endTime = System.currentTimeMillis();  
  59.                     getLog().error("Job " + jobDetail.getKey() +  
  60.                             " threw an unhandled Exception: ", e);  
  61.                     SchedulerException se = new SchedulerException(  
  62.                             "Job threw an unhandled exception.", e);  
  63.                     qs.notifySchedulerListenersError("Job ("  
  64.                             + jec.getJobDetail().getKey()  
  65.                             + " threw an exception.", se);  
  66.                     jobExEx = new JobExecutionException(se, false);  
  67.                 }  
  68.   
  69.                 jec.setJobRunTime(endTime - startTime);  
  70.   
  71.                 // notify all job listeners  
  72.                 if (!notifyJobListenersComplete(jec, jobExEx)) {  
  73.                     break;  
  74.                 }  
  75.   
  76.                 CompletedExecutionInstruction instCode = CompletedExecutionInstruction.NOOP;  
  77.   
  78.                 // update the trigger  
  79.                 try {  
  80.                     instCode = trigger.executionComplete(jec, jobExEx);  
  81.                 } catch (Exception e) {  
  82.                     // If this happens, there's a bug in the trigger...  
  83.                     SchedulerException se = new SchedulerException(  
  84.                             "Trigger threw an unhandled exception.", e);  
  85.                     qs.notifySchedulerListenersError(  
  86.                             "Please report this error to the Quartz developers.",  
  87.                             se);  
  88.                 }  
  89.   
  90.                 // notify all trigger listeners  
  91.                 if (!notifyTriggerListenersComplete(jec, instCode)) {  
  92.                     break;  
  93.                 }  
  94.   
  95.                 // update job/trigger or re-execute job  
  96.                 if (instCode == CompletedExecutionInstruction.RE_EXECUTE_JOB) {  
  97.                     jec.incrementRefireCount();  
  98.                     try {  
  99.                         complete(false);  
  100.                     } catch (SchedulerException se) {  
  101.                         qs.notifySchedulerListenersError("Error executing Job ("  
  102.                                 + jec.getJobDetail().getKey()  
  103.                                 + ": couldn't finalize execution.", se);  
  104.                     }  
  105.                     continue;  
  106.                 }  
  107.   
  108.                 try {  
  109.                     complete(true);  
  110.                 } catch (SchedulerException se) {  
  111.                     qs.notifySchedulerListenersError("Error executing Job ("  
  112.                             + jec.getJobDetail().getKey()  
  113.                             + ": couldn't finalize execution.", se);  
  114.                     continue;  
  115.                 }  
  116.   
  117.                 try {  
  118.                     qs.notifyJobStoreJobComplete(trigger, jobDetail, instCode);  
  119.                 } catch (JobPersistenceException jpe) {  
  120.                     qs.notifySchedulerListenersError(  
  121.                             "An error occured while marking executed job complete. job= '"  
  122.                                     + jobDetail.getKey() + "'", jpe);  
  123.                     if (!completeTriggerRetryLoop(trigger, jobDetail, instCode)) {  
  124.                         return;  
  125.                     }  
  126.                 }  
  127.   
  128.                 break;  
  129.             } while (true);  
  130.   
  131.         } finally {  
  132.             qs.removeInternalSchedulerListener(this);  
  133.         }  
  134.     }  

 3.5SimpleThreadPool

初始化方法:

Java代码
  1. public void initialize() throws SchedulerConfigException {  
  2.   
  3.         if(workers != null && workers.size() > 0// already initialized...  
  4.             return;  
  5.           
  6.         if (count <= 0) {  
  7.             throw new SchedulerConfigException(  
  8.                     "Thread count must be > 0");  
  9.         }  
  10.         if (prio <= 0 || prio > 9) {  
  11.             throw new SchedulerConfigException(  
  12.                     "Thread priority must be > 0 and <= 9");  
  13.         }  
  14.   
  15.         if(isThreadsInheritGroupOfInitializingThread()) {  
  16.             threadGroup = Thread.currentThread().getThreadGroup();  
  17.         } else {  
  18.             // follow the threadGroup tree to the root thread group.  
  19.             threadGroup = Thread.currentThread().getThreadGroup();  
  20.             ThreadGroup parent = threadGroup;  
  21.             while ( !parent.getName().equals("main") ) {  
  22.                 threadGroup = parent;  
  23.                 parent = threadGroup.getParent();  
  24.             }  
  25.             threadGroup = new ThreadGroup(parent, schedulerInstanceName + "-SimpleThreadPool");  
  26.             if (isMakeThreadsDaemons()) {  
  27.                 threadGroup.setDaemon(true);  
  28.             }  
  29.         }  
  30.   
  31.   
  32.         if (isThreadsInheritContextClassLoaderOfInitializingThread()) {  
  33.             getLog().info(  
  34.                     "Job execution threads will use class loader of thread: "  
  35.                             + Thread.currentThread().getName());  
  36.         }  
  37.   
  38.         // create the worker threads and start them  
  39.         Iterator workerThreads = createWorkerThreads(count).iterator();  
  40.         while(workerThreads.hasNext()) {  
  41.             WorkerThread wt = (WorkerThread) workerThreads.next();  
  42.             wt.start();  
  43.             availWorkers.add(wt);  
  44.         }  
  45.     }  

 runInThread方法

Java代码
  1. public boolean runInThread(Runnable runnable) {  
  2.         if (runnable == null) {  
  3.             return false;  
  4.         }  
  5.   
  6.         synchronized (nextRunnableLock) {  
  7.   
  8.             handoffPending = true;  
  9.   
  10.             // Wait until a worker thread is available  
  11.             while ((availWorkers.size() < 1) && !isShutdown) {  
  12.                 try {  
  13.                     nextRunnableLock.wait(500);  
  14.                 } catch (InterruptedException ignore) {  
  15.                 }  
  16.             }  
  17.   
  18.             if (!isShutdown) {  
  19.                 WorkerThread wt = (WorkerThread)availWorkers.removeFirst();  
  20.                 busyWorkers.add(wt);  
  21.                 wt.run(runnable);  
  22.             } else {  
  23.                 // If the thread pool is going down, execute the Runnable  
  24.                 // within a new additional worker thread (no thread from the pool).  
  25.                 WorkerThread wt = new WorkerThread(this, threadGroup,  
  26.                         "WorkerThread-LastJob", prio, isMakeThreadsDaemons(), runnable);  
  27.                 busyWorkers.add(wt);  
  28.                 workers.add(wt);  
  29.                 wt.start();  
  30.             }  
  31.             nextRunnableLock.notifyAll();  
  32.             handoffPending = false;  
  33.         }  
  34.   
  35.         return true;  
  36.     }  

 4..以mysql存储信息方式分析源码

4.1测试配置文件

 

Properties代码
  1. #==============================================================      
  2. #Configure Main Scheduler Properties      
  3. #==============================================================       
  4. org.quartz.scheduler.instanceName = quartzScheduler    
  5. org.quartz.scheduler.instanceId = AUTO    
  6.     
  7. #==============================================================      
  8. #Configure JobStore      
  9. #==============================================================     
  10. org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX    
  11. org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate    
  12. org.quartz.jobStore.tablePrefix = QRTZ_    
  13. org.quartz.jobStore.isClustered = true    
  14. org.quartz.jobStore.clusterCheckinInterval = 20000      
  15. org.quartz.jobStore.dataSource = myDS   
  16.   
  17. org.quartz.jobStore.lockHandler.class=org.quartz.impl.jdbcjobstore.UpdateLockRowSemaphore   
  18.      
  19. #==============================================================      
  20. #Configure DataSource      
  21. #==============================================================     
  22. org.quartz.dataSource.myDS.driver = com.mysql.jdbc.Driver    
  23. org.quartz.dataSource.myDS.URL = jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8  
  24. org.quartz.dataSource.myDS.user = root    
  25. org.quartz.dataSource.myDS.password = password    
  26. org.quartz.dataSource.myDS.maxConnections = 30    
  27.     
  28. #==============================================================      
  29. #Configure ThreadPool      
  30. #==============================================================     
  31. org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool    
  32. org.quartz.threadPool.threadCount = 10    
  33. org.quartz.threadPool.threadPriority = 5    
  34. org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true   

 

 4.2告知JobStore开始执行triggers,更新triggers时间,是在QuartzSchedulerThread的方法中的qsRsrcs.getJobStore().triggersFired(triggers)(该方法通过qrtz_locks表锁来控制并发)

quartz源码浅析_第3张图片
 JobStoreSupport的triggersFired方法
Java代码
  1. public List triggersFired(final List triggers) throws JobPersistenceException {  
  2.     return   
  3.         (List)executeInNonManagedTXLock(  
  4.             LOCK_TRIGGER_ACCESS,  
  5.             new TransactionCallback() {  
  6.                 public Object execute(Connection conn) throws JobPersistenceException {  
  7.                     List results = new ArrayList();  
  8.   
  9.                     TriggerFiredResult result;  
  10.                     for (OperableTrigger trigger : triggers) {  
  11.                         try {  
  12.                           TriggerFiredBundle bundle = triggerFired(conn, trigger);  
  13.                           result = new TriggerFiredResult(bundle);  
  14.                         } catch (JobPersistenceException jpe) {  
  15.                             result = new TriggerFiredResult(jpe);  
  16.                         } catch(RuntimeException re) {  
  17.                             result = new TriggerFiredResult(re);  
  18.                         }  
  19.                         results.add(result);  
  20.                     }  
  21.   
  22.                     return results;  
  23.                 }  
  24.             });  
  25. }  
 JobStoreSupport的executeInNonManagedTXLock方法
Java代码
  1. protected Object executeInNonManagedTXLock(  
  2.             String lockName,   
  3.             TransactionCallback txCallback) throws JobPersistenceException {  
  4.         boolean transOwner = false;  
  5.         Connection conn = null;  
  6.         try {  
  7.             if (lockName != null) {  
  8.                 // If we aren't using db locks, then delay getting DB connection   
  9.                 // until after acquiring the lock since it isn't needed.  
  10.                 if (getLockHandler().requiresConnection()) {  
  11.                     conn = getNonManagedTXConnection();  
  12.                 }  
  13.                   
  14.                 transOwner = getLockHandler().obtainLock(conn, lockName);  
  15.             }  
  16.               
  17.             if (conn == null) {  
  18.                 conn = getNonManagedTXConnection();  
  19.             }  
  20.               
  21.             Object result = txCallback.execute(conn);  
  22.             commitConnection(conn);  
  23.   
  24.             Long sigTime = clearAndGetSignalSchedulingChangeOnTxCompletion();  
  25.             if(sigTime != null && sigTime >= 0) {  
  26.                 signalSchedulingChangeImmediately(sigTime);  
  27.             }  
  28.               
  29.             return result;  
  30.         } catch (JobPersistenceException e) {  
  31.             rollbackConnection(conn);  
  32.             throw e;  
  33.         } catch (RuntimeException e) {  
  34.             rollbackConnection(conn);  
  35.             throw new JobPersistenceException("Unexpected runtime exception: "  
  36.                     + e.getMessage(), e);  
  37.         } finally {  
  38.             try {  
  39.                 releaseLock(conn, lockName, transOwner);  
  40.             } finally {  
  41.                 cleanupConnection(conn);  
  42.             }  
  43.         }  
  44.     }  
 JobStoreSupport的triggersFired方法
Java代码
  1. public List triggersFired(final List triggers) throws JobPersistenceException {  
  2.         return   
  3.             (List)executeInNonManagedTXLock(  
  4.                 LOCK_TRIGGER_ACCESS,  
  5.                 new TransactionCallback() {  
  6.                     public Object execute(Connection conn) throws JobPersistenceException {  
  7.                         List results = new ArrayList();  
  8.   
  9.                         TriggerFiredResult result;  
  10.                         for (OperableTrigger trigger : triggers) {  
  11.                             try {  
  12.                               TriggerFiredBundle bundle = triggerFired(conn, trigger);  
  13.                               result = new TriggerFiredResult(bundle);  
  14.                             } catch (JobPersistenceException jpe) {  
  15.                                 result = new TriggerFiredResult(jpe);  
  16.                             } catch(RuntimeException re) {  
  17.                                 result = new TriggerFiredResult(re);  
  18.                             }  
  19.                             results.add(result);  
  20.                         }  
  21.   
  22.                         return results;  
  23.                     }  
  24.                 });  
  25.     }  
  JobStoreSupport的triggerFired方法
Java代码
  1. protected TriggerFiredBundle triggerFired(Connection conn,  
  2.            OperableTrigger trigger)  
  3.        throws JobPersistenceException {  
  4.        JobDetail job = null;  
  5.        Calendar cal = null;  
  6.   
  7.        // Make sure trigger wasn't deleted, paused, or completed...  
  8.        try { // if trigger was deleted, state will be STATE_DELETED  
  9.            String state = getDelegate().selectTriggerState(conn,  
  10.                    trigger.getKey());  
  11.            if (!state.equals(STATE_ACQUIRED)) {  
  12.                return null;  
  13.            }  
  14.        } catch (SQLException e) {  
  15.            throw new JobPersistenceException("Couldn't select trigger state: "  
  16.                    + e.getMessage(), e);  
  17.        }  
  18.   
  19.        try {  
  20.            job = retrieveJob(conn, trigger.getJobKey());  
  21.            if (job == null) { return null; }  
  22.        } catch (JobPersistenceException jpe) {  
  23.            try {  
  24.                getLog().error("Error retrieving job, setting trigger state to ERROR.", jpe);  
  25.                getDelegate().updateTriggerState(conn, trigger.getKey(),  
  26.                        STATE_ERROR);  
  27.            } catch (SQLException sqle) {  
  28.                getLog().error("Unable to set trigger state to ERROR.", sqle);  
  29.            }  
  30.            throw jpe;  
  31.        }  
  32.   
  33.        if (trigger.getCalendarName() != null) {  
  34.            cal = retrieveCalendar(conn, trigger.getCalendarName());  
  35.            if (cal == null) { return null; }  
  36.        }  
  37.   
  38.        try {  
  39.            getDelegate().updateFiredTrigger(conn, trigger, STATE_EXECUTING, job);  
  40.        } catch (SQLException e) {  
  41.            throw new JobPersistenceException("Couldn't insert fired trigger: "  
  42.                    + e.getMessage(), e);  
  43.        }  
  44.   
  45.        Date prevFireTime = trigger.getPreviousFireTime();  
  46.   
  47.        // call triggered - to update the trigger's next-fire-time state...  
  48.        trigger.triggered(cal);  
  49.   
  50.        String state = STATE_WAITING;  
  51.        boolean force = true;  
  52.          
  53.        if (job.isConcurrentExectionDisallowed()) {  
  54.            state = STATE_BLOCKED;  
  55.            force = false;  
  56.            try {  
  57.                getDelegate().updateTriggerStatesForJobFromOtherState(conn, job.getKey(),  
  58.                        STATE_BLOCKED, STATE_WAITING);  
  59.                getDelegate().updateTriggerStatesForJobFromOtherState(conn, job.getKey(),  
  60.                        STATE_BLOCKED, STATE_ACQUIRED);  
  61.                getDelegate().updateTriggerStatesForJobFromOtherState(conn, job.getKey(),  
  62.                        STATE_PAUSED_BLOCKED, STATE_PAUSED);  
  63.            } catch (SQLException e) {  
  64.                throw new JobPersistenceException(  
  65.                        "Couldn't update states of blocked triggers: "  
  66.                                + e.getMessage(), e);  
  67.            }  
  68.        }   
  69.              
  70.        if (trigger.getNextFireTime() == null) {  
  71.            state = STATE_COMPLETE;  
  72.            force = true;  
  73.        }  
  74.   
  75.        storeTrigger(conn, trigger, job, true, state, force, false);  
  76.   
  77.        job.getJobDataMap().clearDirtyFlag();  
  78.   
  79.        return new TriggerFiredBundle(job, trigger, cal, trigger.getKey().getGroup()  
  80.                .equals(Scheduler.DEFAULT_RECOVERY_GROUP), new Date(), trigger  
  81.                .getPreviousFireTime(), prevFireTime, trigger.getNextFireTime());  
  82.    }  
 JobStoreSupport的storeTrigger方法
 
Java代码
  1. protected void storeTrigger(Connection conn,   
  2.             OperableTrigger newTrigger, JobDetail job, boolean replaceExisting, String state,  
  3.             boolean forceState, boolean recovering)  
  4.         throws ObjectAlreadyExistsException, JobPersistenceException {  
  5.   
  6.         boolean existingTrigger = triggerExists(conn, newTrigger.getKey());  
  7.   
  8.         if ((existingTrigger) && (!replaceExisting)) {   
  9.             throw new ObjectAlreadyExistsException(newTrigger);   
  10.         }  
  11.           
  12.         try {  
  13.   
  14.             boolean shouldBepaused = false;  
  15.   
  16.             if (!forceState) {  
  17.                 shouldBepaused = getDelegate().isTriggerGroupPaused(  
  18.                         conn, newTrigger.getKey().getGroup());  
  19.   
  20.                 if(!shouldBepaused) {  
  21.                     shouldBepaused = getDelegate().isTriggerGroupPaused(conn,  
  22.                             ALL_GROUPS_PAUSED);  
  23.   
  24.                     if (shouldBepaused) {  
  25.                         getDelegate().insertPausedTriggerGroup(conn, newTrigger.getKey().getGroup());  
  26.                     }  
  27.                 }  
  28.   
  29.                 if (shouldBepaused && (state.equals(STATE_WAITING) || state.equals(STATE_ACQUIRED))) {  
  30.                     state = STATE_PAUSED;  
  31.                 }  
  32.             }  
  33.   
  34.             if(job == null) {  
  35.                 job = getDelegate().selectJobDetail(conn, newTrigger.getJobKey(), getClassLoadHelper());  
  36.             }  
  37.             if (job == null) {  
  38.                 throw new JobPersistenceException("The job ("  
  39.                         + newTrigger.getJobKey()  
  40.                         + ") referenced by the trigger does not exist.");  
  41.             }  
  42.   
  43.             if (job.isConcurrentExectionDisallowed() && !recovering) {   
  44.                 state = checkBlockedState(conn, job.getKey(), state);  
  45.             }  
  46.               
  47.             if (existingTrigger) {  
  48.                 getDelegate().updateTrigger(conn, newTrigger, state, job);  
  49.             } else {  
  50.                 getDelegate().insertTrigger(conn, newTrigger, state, job);  
  51.             }  
  52.         } catch (Exception e) {  
  53.             throw new JobPersistenceException("Couldn't store trigger '" + newTrigger.getKey() + "' for '"   
  54.                     + newTrigger.getJobKey() + "' job:" + e.getMessage(), e);  
  55.         }  
  56.     }  
 StdJDBCDelegate的updateTrigger方法

 

Java代码
  1. public int updateTrigger(Connection conn, OperableTrigger trigger, String state,  
  2.             JobDetail jobDetail) throws SQLException, IOException {  
  3.   
  4.         // save some clock cycles by unnecessarily writing job data blob ...  
  5.         boolean updateJobData = trigger.getJobDataMap().isDirty();  
  6.         ByteArrayOutputStream baos = null;  
  7.         if(updateJobData && trigger.getJobDataMap().size() > 0) {  
  8.             baos = serializeJobData(trigger.getJobDataMap());  
  9.         }  
  10.                   
  11.         PreparedStatement ps = null;  
  12.   
  13.         int insertResult = 0;  
  14.   
  15.   
  16.         try {  
  17.             if(updateJobData) {  
  18.                 ps = conn.prepareStatement(rtp(UPDATE_TRIGGER));  
  19.             } else {  
  20.                 ps = conn.prepareStatement(rtp(UPDATE_TRIGGER_SKIP_DATA));  
  21.             }  
  22.                   
  23.             ps.setString(1, trigger.getJobKey().getName());  
  24.             ps.setString(2, trigger.getJobKey().getGroup());  
  25.             ps.setString(3, trigger.getDescription());  
  26.             long nextFireTime = -1;  
  27.             if (trigger.getNextFireTime() != null) {  
  28.                 nextFireTime = trigger.getNextFireTime().getTime();  
  29.             }  
  30.             ps.setBigDecimal(4new BigDecimal(String.valueOf(nextFireTime)));  
  31.             long prevFireTime = -1;  
  32.             if (trigger.getPreviousFireTime() != null) {  
  33.                 prevFireTime = trigger.getPreviousFireTime().getTime();  
  34.             }  
  35.             ps.setBigDecimal(5new BigDecimal(String.valueOf(prevFireTime)));  
  36.             ps.setString(6, state);  
  37.               
  38.             TriggerPersistenceDelegate tDel = findTriggerPersistenceDelegate(trigger);  
  39.               
  40.             String type = TTYPE_BLOB;  
  41.             if(tDel != null)  
  42.                 type = tDel.getHandledTriggerTypeDiscriminator();  
  43.   
  44.             ps.setString(7, type);  
  45.               
  46.             ps.setBigDecimal(8new BigDecimal(String.valueOf(trigger  
  47.                     .getStartTime().getTime())));  
  48.             long endTime = 0;  
  49.             if (trigger.getEndTime() != null) {  
  50.                 endTime = trigger.getEndTime().getTime();  
  51.             }  
  52.             ps.setBigDecimal(9new BigDecimal(String.valueOf(endTime)));  
  53.             ps.setString(10, trigger.getCalendarName());  
  54.             ps.setInt(11, trigger.getMisfireInstruction());  
  55.             ps.setInt(12, trigger.getPriority());  
  56.   
  57.             if(updateJobData) {  
  58.                 setBytes(ps, 13, baos);  
  59.                 ps.setString(14, trigger.getKey().getName());  
  60.                 ps.setString(15, trigger.getKey().getGroup());  
  61.             } else {  
  62.                 ps.setString(13, trigger.getKey().getName());  
  63.                 ps.setString(14, trigger.getKey().getGroup());  
  64.             }  
  65.   
  66.             insertResult = ps.executeUpdate();  
  67.               
  68.             if(tDel == null)  
  69.                 updateBlobTrigger(conn, trigger);  
  70.             else  
  71.                 tDel.updateExtendedTriggerProperties(conn, trigger, state, jobDetail);  
  72.               
  73.         } finally {  
  74.             closeStatement(ps);  
  75.         }  
  76.   
  77.         return insertResult;  
  78.     }  

  4.3锁机制

通过配置文件配置org.quartz.jobStore.lockHandler.class

DBSemaphore的实现由2个

UpdateLockRowSemaphore以update获取锁

Java代码
  1. public static final String UPDATE_FOR_LOCK =  
  2.        "UPDATE " + TABLE_PREFIX_SUBST + TABLE_LOCKS +  
  3.        " SET " + COL_LOCK_NAME + " = " + COL_LOCK_NAME +  
  4.        " WHERE " + COL_SCHEDULER_NAME + " = " + SCHED_NAME_SUBST  
  5.        + " AND " + COL_LOCK_NAME + " = ? ";  

 

StdRowLockSemaphore以select ``` from update获取锁

Java代码
  1. public static final String SELECT_FOR_LOCK = "SELECT * FROM "  
  2.         + TABLE_PREFIX_SUBST + TABLE_LOCKS + " WHERE " + COL_SCHEDULER_NAME + " = " + SCHED_NAME_SUBST  
  3.         + " AND " + COL_LOCK_NAME + " = ? FOR UPDATE";  

 注:本文quartz版本为2.0.2

你可能感兴趣的:(quartz)