quartz使用及原理解析

news2024/11/18 3:25:34

quartz简介

​ Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,完全由Java开发,可以用来执行定时任务,类似于java.util.Timer。但是相较于Timer, Quartz增加了很多功能:

  • 持久性作业 - 就是保持调度定时的状态;

  • 作业管理 - 对调度作业进行有效的管理;

    官方文档:

  • http://www.quartz-scheduler.org/documentation/

  • http://www.quartz-scheduler.org/api/2.3.0/index.html

quartz的使用

非Spring环境

引入

<!-- 核心包 -->
<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.3.0</version>
</dependency>
<!-- 工具包 -->
<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz-jobs</artifactId>
    <version>2.3.0</version>
</dependency>

编码

1、新建一个任务,实现 org.quartz.Job 接口:

public class MyJob implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("任务被执行了。。。");
    }
}

2、创建调度器、jobDetail 实例、trigger 实例、执行

public static void main(String[] args) throws Exception {
    // 1.创建调度器 Scheduler
    SchedulerFactory factory = new StdSchedulerFactory();
    Scheduler scheduler = factory.getScheduler();

    // 2.创建JobDetail实例,并与MyJob类绑定(Job执行内容)
    JobDetail job = JobBuilder.newJob(MyJob.class)
        .withIdentity("job1", "group1")
        .build();

    // 3.构建Trigger实例,每隔30s执行一次
    Trigger trigger = TriggerBuilder.newTrigger()
        .withIdentity("trigger1", "group1")
        .startNow()
        //设置跑在哪个scheduler上,频率是什么
        .withSchedule(simpleSchedule()
                      .withIntervalInSeconds(30)
                      .repeatForever())
        .build();

    // 4.执行,开启调度器
    scheduler.scheduleJob(job, trigger);
    System.out.println(System.currentTimeMillis());
    scheduler.start();

    //主线程睡眠1分钟,然后关闭调度器
    TimeUnit.MINUTES.sleep(1);
    scheduler.shutdown();
    System.out.println(System.currentTimeMillis());
}

与Spring boot集成

引入

<!--  Quartz 任务调度 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

默认在spring-boot-autoconfigure jar包中已自动配置。包 org.springframework.boot.autoconfigure.quartz

编码

​ 同上。

其他说明

​ Quartz定时任务默认都是并发执行的,不会等待上一次任务执行完毕,只要间隔时间到就会执行, 如果定时任执行太长,会长时间占用资源,导致其它任务堵塞。

@DisallowConcurrentExecution 禁止并发执行多个相同定义的JobDetail, 这个注解是加在Job类上的, 但意思并不是不能同时执行多个Job, 而是不能并发执行同一个Job Definition(由JobDetail定义), 但是可以同时执行多个不同的JobDetail。

@PersistJobDataAfterExecution 同样, 也是加在Job上。表示当正常执行完Job后, JobDataMap中的数据应该被改动, 以被下一次调用时用。

​ 当使用 @PersistJobDataAfterExecution 注解时, 为了避免并发时, 存储数据造成混乱, 强烈建议把 @DisallowConcurrentExecution 注解也加上。

阻止特定时间运行

//2014-8-15这一天不执行任何任务
Calendar c = new GregorianCalendar(2014, 7, 15);
cal.setDayExcluded(c, true);
scheduler.addCalendar("exclude", cal, false, false);

核心类介绍

​ Quartz 的核心类有以下三部分:

  • 任务 Job : 需要实现的任务类,实现 execute() 方法,执行后完成任务。
  • 触发器 Trigger : 包括 SimpleTriggerCronTrigger
  • 调度器 Scheduler : 任务调度器,负责基于 Trigger触发器,来执行 Job任务

JobDetail

​ JobDetail 的作用是绑定 Job,是一个任务实例,它为 Job 添加了许多扩展参数。

​ 每次Scheduler调度执行一个Job的时候,首先会拿到对应的Job的类,然后创建该Job实例,再去执行Job中的execute()的内容,任务执行结束后,关联的Job对象实例会被释放,且会被JVM GC清除。

​ JobDetail 就是一个Job实例的包装类。Sheduler每次执行,都会根据新的Job实例,这样就可以 规避并发访问 的问题。

JobExecutionContext

  • Scheduler 调用一个 job,就会将 JobExecutionContext 传递给 Job 的 execute() 方法;
  • Job 能通过 JobExecutionContext 对象访问到 Quartz 运行时候的环境以及 Job 本身的明细数据。

JobDataMap

​ 有状态的 job 可以理解为多次 job调用期间可以持有一些状态信息,这些状态信息存储在 JobDataMap 中。

而默认的无状态 job,每次调用时都会创建一个新的 JobDataMap

让Job支持有状态,则需要在Job类上加注解 @PersistJobDataAfterExecution

Trigger

Trigger 可以设置任务的开始结束时间, Scheduler 会根据参数进行触发。

Calendar

​ 一个Trigger可以和多个Calendar关联,以便排除或包含某些时间点。例如:每周星期一早上10:00执行任务,但是如果碰到法定的节日,则不执行,这时就需要在Trigger触发机制的基础上使用Calendar进行定点排除。

public interface Calendar extends java.io.Serializable, java.lang.Cloneable {
    int MONTH = 0;
    void setBaseCalendar(Calendar baseCalendar);
    Calendar getBaseCalendar();
    boolean isTimeIncluded(long timeStamp);
    //获取给定时间之后的下一个include 时间。
    long getNextIncludedTime(long timeStamp);
    String getDescription();
    void setDescription(String description);
    Object clone();
}
Calendar 名称用法精度
BaseCalendar为高级的 Calendar 实现了基本的功能,实现了 org.quartz.Calendar 接口
AnnualCalendar指定年中一天或多天。忽略年份。
CronCalendar指定CronExpression表达的时间集合。
DailyCalendar每个DailyCalendar仅允许指定单个时间范围,并且该时间范围可能不会跨越每日边界(即,您不能指定从上午8点至凌晨5点的时间范围)。 如果属性invertTimeRange为false(默认),则时间范围定义触发器不允许触发的时间范围。 如果invertTimeRange为true,则时间范围被反转 - 也就是排除在定义的时间范围之外的所有时间。毫秒
HolidayCalendar从 Trigger 中排除/包含节假日
MonthlyCalendar排除/包含月份中的指定数天
WeeklyCalendar排除/包含星期中的任意周几

源码解析

配置

QuartzAutoConfiguration

quartz在Spring boot 中 通过 在spring-boot-autoconfigure jar中的包 org.springframework.boot.autoconfigure.quartz下的 QuartzAutoConfiguration 类进行配置。

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ Scheduler.class, SchedulerFactoryBean.class, PlatformTransactionManager.class })
@EnableConfigurationProperties(QuartzProperties.class)
@AutoConfigureAfter({ DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class,
		LiquibaseAutoConfiguration.class, FlywayAutoConfiguration.class })
public class QuartzAutoConfiguration {

	@Bean
	@ConditionalOnMissingBean
	public SchedulerFactoryBean quartzScheduler(QuartzProperties properties,
			ObjectProvider<SchedulerFactoryBeanCustomizer> customizers, ObjectProvider<JobDetail> jobDetails,
			Map<String, Calendar> calendars, ObjectProvider<Trigger> triggers, ApplicationContext applicationContext) {
		SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
		SpringBeanJobFactory jobFactory = new SpringBeanJobFactory();
		jobFactory.setApplicationContext(applicationContext);
		schedulerFactoryBean.setJobFactory(jobFactory);
		if (properties.getSchedulerName() != null) {
			schedulerFactoryBean.setSchedulerName(properties.getSchedulerName());
		}
		schedulerFactoryBean.setAutoStartup(properties.isAutoStartup());
		schedulerFactoryBean.setStartupDelay((int) properties.getStartupDelay().getSeconds());
		schedulerFactoryBean.setWaitForJobsToCompleteOnShutdown(properties.isWaitForJobsToCompleteOnShutdown());
		schedulerFactoryBean.setOverwriteExistingJobs(properties.isOverwriteExistingJobs());
		if (!properties.getProperties().isEmpty()) {
			schedulerFactoryBean.setQuartzProperties(asProperties(properties.getProperties()));
		}
		schedulerFactoryBean.setJobDetails(jobDetails.orderedStream().toArray(JobDetail[]::new));
		schedulerFactoryBean.setCalendars(calendars);
		schedulerFactoryBean.setTriggers(triggers.orderedStream().toArray(Trigger[]::new));
		customizers.orderedStream().forEach((customizer) -> customizer.customize(schedulerFactoryBean));
		return schedulerFactoryBean;
	}

	private Properties asProperties(Map<String, String> source) {
		Properties properties = new Properties();
		properties.putAll(source);
		return properties;
	}

	@Configuration(proxyBeanMethods = false)
	@ConditionalOnSingleCandidate(DataSource.class)
	@ConditionalOnProperty(prefix = "spring.quartz", name = "job-store-type", havingValue = "jdbc")
	protected static class JdbcStoreTypeConfiguration {

		@Bean
		@Order(0)
		public SchedulerFactoryBeanCustomizer dataSourceCustomizer(QuartzProperties properties, DataSource dataSource,
				@QuartzDataSource ObjectProvider<DataSource> quartzDataSource,
				ObjectProvider<PlatformTransactionManager> transactionManager) {
			return (schedulerFactoryBean) -> {
				DataSource dataSourceToUse = getDataSource(dataSource, quartzDataSource);
				schedulerFactoryBean.setDataSource(dataSourceToUse);
				PlatformTransactionManager txManager = transactionManager.getIfUnique();
				if (txManager != null) {
					schedulerFactoryBean.setTransactionManager(txManager);
				}
			};
		}

		private DataSource getDataSource(DataSource dataSource, ObjectProvider<DataSource> quartzDataSource) {
			DataSource dataSourceIfAvailable = quartzDataSource.getIfAvailable();
			return (dataSourceIfAvailable != null) ? dataSourceIfAvailable : dataSource;
		}

		@Bean
		@ConditionalOnMissingBean
		public QuartzDataSourceInitializer quartzDataSourceInitializer(DataSource dataSource,
				@QuartzDataSource ObjectProvider<DataSource> quartzDataSource, ResourceLoader resourceLoader,
				QuartzProperties properties) {
			DataSource dataSourceToUse = getDataSource(dataSource, quartzDataSource);
			return new QuartzDataSourceInitializer(dataSourceToUse, resourceLoader, properties);
		}

		/**
		 * Additional configuration to ensure that {@link SchedulerFactoryBean} and
		 * {@link Scheduler} beans depend on any beans that perform data source
		 * initialization.
		 */
		@Configuration(proxyBeanMethods = false)
		static class QuartzSchedulerDependencyConfiguration {

			@Bean
			static SchedulerDependsOnBeanFactoryPostProcessor quartzSchedulerDataSourceInitializerDependsOnBeanFactoryPostProcessor() {
				return new SchedulerDependsOnBeanFactoryPostProcessor(QuartzDataSourceInitializer.class);
			}

			@Bean
			@ConditionalOnBean(FlywayMigrationInitializer.class)
			static SchedulerDependsOnBeanFactoryPostProcessor quartzSchedulerFlywayDependsOnBeanFactoryPostProcessor() {
				return new SchedulerDependsOnBeanFactoryPostProcessor(FlywayMigrationInitializer.class);
			}

			@Configuration(proxyBeanMethods = false)
			@ConditionalOnClass(SpringLiquibase.class)
			static class LiquibaseQuartzSchedulerDependencyConfiguration {

				@Bean
				@ConditionalOnBean(SpringLiquibase.class)
				static SchedulerDependsOnBeanFactoryPostProcessor quartzSchedulerLiquibaseDependsOnBeanFactoryPostProcessor() {
					return new SchedulerDependsOnBeanFactoryPostProcessor(SpringLiquibase.class);
				}

			}

		}

	}

	/**
	 * {@link AbstractDependsOnBeanFactoryPostProcessor} for Quartz {@link Scheduler} and
	 * {@link SchedulerFactoryBean}.
	 */
	private static class SchedulerDependsOnBeanFactoryPostProcessor extends AbstractDependsOnBeanFactoryPostProcessor {

		SchedulerDependsOnBeanFactoryPostProcessor(Class<?>... dependencyTypes) {
			super(Scheduler.class, SchedulerFactoryBean.class, dependencyTypes);
		}

	}

}

在创建 SchedulerFactoryBean 时 ,会把设置JobDetails,Triggers。

SchedulerFactoryBean 可以通过 SchedulerFactoryBeanCustomizer 来设置属性。

@FunctionalInterface
public interface SchedulerFactoryBeanCustomizer {

	/**
	 * Customize the {@link SchedulerFactoryBean}.
	 * @param schedulerFactoryBean the scheduler to customize
	 */
	void customize(SchedulerFactoryBean schedulerFactoryBean);

}

QuartzProperties

quartz 的 配置通过 spring.quartz 参数 配置。

quartz.properties里边的配置,都可以放到application.yml里的spring. quartz.properties下边

spring:
  quartz:
    properties:
      org:
        quartz:
          threadPool:
            threadCount: 10
            threadPriority: 5
          jobStore:
            misfireThreshold: 50000
@ConfigurationProperties("spring.quartz")
public class QuartzProperties {
    /**
	 * Quartz job store type.
	 */
	private JobStoreType jobStoreType = JobStoreType.MEMORY;
	private String schedulerName;
	private boolean autoStartup = true;
	private Duration startupDelay = Duration.ofSeconds(0);
	private boolean waitForJobsToCompleteOnShutdown = false;
	private boolean overwriteExistingJobs = false;

	/**
	 * spring. quartz.properties
	 */
	private final Map<String, String> properties = new HashMap<>();

	private final Jdbc jdbc = new Jdbc();

    
}

加载配置过程

1、获取spring 配置

		//QuartzAutoConfiguration.QuartzAutoConfiguration
		if (!properties.getProperties().isEmpty()) {
			schedulerFactoryBean.setQuartzProperties(asProperties(properties.getProperties()));
		}

2、合并一些配置,并初始化

//SchedulerFactoryBean	
private void initSchedulerFactory(StdSchedulerFactory schedulerFactory) throws SchedulerException, IOException {
		Properties mergedProps = new Properties();
		if (this.resourceLoader != null) {
			mergedProps.setProperty(StdSchedulerFactory.PROP_SCHED_CLASS_LOAD_HELPER_CLASS,
					ResourceLoaderClassLoadHelper.class.getName());
		}

		if (this.taskExecutor != null) {
			mergedProps.setProperty(StdSchedulerFactory.PROP_THREAD_POOL_CLASS,
					LocalTaskExecutorThreadPool.class.getName());
		}
		else {
			// Set necessary default properties here, as Quartz will not apply
			// its default configuration when explicitly given properties.
			mergedProps.setProperty(StdSchedulerFactory.PROP_THREAD_POOL_CLASS, SimpleThreadPool.class.getName());
			mergedProps.setProperty(PROP_THREAD_COUNT, Integer.toString(DEFAULT_THREAD_COUNT));
		}
         // 加载配置文件中的配置 
		if (this.configLocation != null) {
			if (logger.isDebugEnabled()) {
				logger.debug("Loading Quartz config from [" + this.configLocation + "]");
			}
			PropertiesLoaderUtils.fillProperties(mergedProps, this.configLocation);
		}
         //合并 配置
		CollectionUtils.mergePropertiesIntoMap(this.quartzProperties, mergedProps);
		if (this.dataSource != null) {
			mergedProps.setProperty(StdSchedulerFactory.PROP_JOB_STORE_CLASS, LocalDataSourceJobStore.class.getName());
		}

		// Determine scheduler name across local settings and Quartz properties...
		if (this.schedulerName != null) {
			mergedProps.setProperty(StdSchedulerFactory.PROP_SCHED_INSTANCE_NAME, this.schedulerName);
		}
		else {
			String nameProp = mergedProps.getProperty(StdSchedulerFactory.PROP_SCHED_INSTANCE_NAME);
			if (nameProp != null) {
				this.schedulerName = nameProp;
			}
			else if (this.beanName != null) {
				mergedProps.setProperty(StdSchedulerFactory.PROP_SCHED_INSTANCE_NAME, this.beanName);
				this.schedulerName = this.beanName;
			}
		}
         //初始化
		schedulerFactory.initialize(mergedProps);
	}

image-20230107104024616

调度

quartz使用 SchedulerFactory 来实例化一个 调度器 。

SchedulerFactory

public interface SchedulerFactory {
    Scheduler getScheduler() throws SchedulerException;
    Scheduler getScheduler(String schedName) throws SchedulerException;
    Collection<Scheduler> getAllSchedulers() throws SchedulerException;

}

quartz为SchedulerFactory实现了2个实现类。

  • StdSchedulerFactory:创建scheduler的标准工厂。
  • DirectSchedulerFactory :直接创建scheduler的工厂,简单的单例实现,提供一些便捷方式。没有复杂的配置。

StdSchedulerFactory

​ 创建scheduler的标准工厂。

​ 通常是通过quartz.properties属性配置文件(默认情况下均使用该文件)结合StdSchedulerFactory 来使用Quartz的。StdSchedulerFactory 会加载属性配置文件并实例化一个Scheduler

DirectSchedulerFactory

Scheduler

​ Scheduler 维护了一个 JobDetails 和 Triggers 的注册表。
​ 一旦在 Scheduler 注册过了,当定时任务触发时间一到,调度程序就会负责执行预先定义的 Job调度程序创建之后,处于 “ 待机 ” 状态,必须调用 scheduler 的 start() 方法启用调度程序可以使用 shutdown() 方法关闭调度程序,使用 isShutdown() 方法判断该调度程序是否已经处于关闭状态
通过 Scheduler.scheduleJob(…) 方法将任务纳入调度程序中,当任务触发时间到了的时候,该任务将被
执行
​ quartz的实现类如下:

image-20230106101310395
public interface Scheduler {
    //默认 Group:DEFAULT,用于Job,Trigger。
    String DEFAULT_GROUP = Key.DEFAULT_GROUP;
    String DEFAULT_RECOVERY_GROUP = "RECOVERING_JOBS";

    /** 用于Trigger     */
    String DEFAULT_FAIL_OVER_GROUP = "FAILED_OVER_JOBS";
    String FAILED_JOB_ORIGINAL_TRIGGER_NAME =  "QRTZ_FAILED_JOB_ORIG_TRIGGER_NAME";
    String FAILED_JOB_ORIGINAL_TRIGGER_GROUP =  "QRTZ_FAILED_JOB_ORIG_TRIGGER_GROUP";
    String FAILED_JOB_ORIGINAL_TRIGGER_FIRETIME_IN_MILLISECONDS =  "QRTZ_FAILED_JOB_ORIG_TRIGGER_FIRETIME_IN_MILLISECONDS_AS_STRING";

    String FAILED_JOB_ORIGINAL_TRIGGER_SCHEDULED_FIRETIME_IN_MILLISECONDS =  "QRTZ_FAILED_JOB_ORIG_TRIGGER_SCHEDULED_FIRETIME_IN_MILLISECONDS_AS_STRING";

    String getSchedulerName() throws SchedulerException;
    String getSchedulerInstanceId() throws SchedulerException;
    SchedulerContext getContext() throws SchedulerException;

    /**
    Scheduler 创建时的状态为:stand-by。不能执行触发器。必须启动之后。
    */
    void start() throws SchedulerException;

    /**
    延迟多久启动
    **/
    void startDelayed(int seconds) throws SchedulerException;    
    boolean isStarted() throws SchedulerException;
    
    /**
     * 切回 stand-by 模式。
     */
    void standby() throws SchedulerException;
    boolean isInStandbyMode() throws SchedulerException;

    /**
     * 关闭 scheduler。不能再重新启动了。
     * 等同 shutdown(false)
     */
    void shutdown() throws SchedulerException;

    /**
     * @param waitForJobsToComplete,为true,表示一直阻塞 所有任务执行完成。
     */
    void shutdown(boolean waitForJobsToComplete)
        throws SchedulerException;
    boolean isShutdown() throws SchedulerException;
    SchedulerMetaData getMetaData() throws SchedulerException;

    /** 获取所有正在执行的任务
     */
    List<JobExecutionContext> getCurrentlyExecutingJobs() throws SchedulerException;
    void setJobFactory(JobFactory factory) throws SchedulerException;
    
    ListenerManager getListenerManager()  throws SchedulerException;

    /**调度一个任务
     */
    Date scheduleJob(JobDetail jobDetail, Trigger trigger)
        throws SchedulerException;

    Date scheduleJob(Trigger trigger) throws SchedulerException;

    void scheduleJobs(Map<JobDetail, Set<? extends Trigger>> triggersAndJobs, boolean replace) throws SchedulerException;
    
    void scheduleJob(JobDetail jobDetail, Set<? extends Trigger> triggersForJob, boolean replace) throws SchedulerException;
    
    /**取消调度 */
    boolean unscheduleJob(TriggerKey triggerKey)
        throws SchedulerException;

    boolean unscheduleJobs(List<TriggerKey> triggerKeys)
        throws SchedulerException;
    
    Date rescheduleJob(TriggerKey triggerKey, Trigger newTrigger) 
        throws SchedulerException;
   
    void addJob(JobDetail jobDetail, boolean replace)
        throws SchedulerException;

    void addJob(JobDetail jobDetail, boolean replace, boolean storeNonDurableWhileAwaitingScheduling)
            throws SchedulerException;

    boolean deleteJob(JobKey jobKey)
        throws SchedulerException;

    boolean deleteJobs(List<JobKey> jobKeys)
        throws SchedulerException;
    
    void triggerJob(JobKey jobKey)
        throws SchedulerException;


    void triggerJob(JobKey jobKey, JobDataMap data)
        throws SchedulerException;
    void pauseJob(JobKey jobKey)
        throws SchedulerException;

    void pauseJobs(GroupMatcher<JobKey> matcher) throws SchedulerException;

    void pauseTrigger(TriggerKey triggerKey)
        throws SchedulerException;

    void pauseTriggers(GroupMatcher<TriggerKey> matcher) throws SchedulerException;

    void resumeJob(JobKey jobKey)
        throws SchedulerException;

    void resumeJobs(GroupMatcher<JobKey> matcher) throws SchedulerException;

    void resumeTrigger(TriggerKey triggerKey)
        throws SchedulerException;

    void resumeTriggers(GroupMatcher<TriggerKey> matcher) throws SchedulerException;
    void pauseAll() throws SchedulerException;
    void resumeAll() throws SchedulerException;

    List<String> getJobGroupNames() throws SchedulerException;

    Set<JobKey> getJobKeys(GroupMatcher<JobKey> matcher) throws SchedulerException;
    List<? extends Trigger> getTriggersOfJob(JobKey jobKey)
        throws SchedulerException;
    List<String> getTriggerGroupNames() throws SchedulerException;

    Set<TriggerKey> getTriggerKeys(GroupMatcher<TriggerKey> matcher) throws SchedulerException;

    Set<String> getPausedTriggerGroups() throws SchedulerException;
    
    JobDetail getJobDetail(JobKey jobKey)
        throws SchedulerException;

    Trigger getTrigger(TriggerKey triggerKey)
        throws SchedulerException;


    TriggerState getTriggerState(TriggerKey triggerKey)
        throws SchedulerException;

    void addCalendar(String calName, Calendar calendar, boolean replace, boolean updateTriggers)
        throws SchedulerException;

    boolean deleteCalendar(String calName) throws SchedulerException;

    Calendar getCalendar(String calName) throws SchedulerException;

    List<String> getCalendarNames() throws SchedulerException;

     
    boolean interrupt(JobKey jobKey) throws UnableToInterruptJobException;
     
    boolean interrupt(String fireInstanceId) throws UnableToInterruptJobException;
     
    boolean checkExists(JobKey jobKey) throws SchedulerException; 
    
    boolean checkExists(TriggerKey triggerKey) throws SchedulerException;
     
    void clear() throws SchedulerException;
}

StdScheduler

标准Scheduler,主要功能是通过内部的 QuartzScheduler实现。

附录

参考

​ http://www.quartz-scheduler.org/documentation/quartz-2.3.0/cookbook/

​ http://www.quartz-scheduler.org/documentation/quartz-2.3.0/configuration/

配置

主要配置

属性名称必需类型默认值
org.quartz.scheduler.instanceNamenostring‘QuartzScheduler’
org.quartz.scheduler.instanceIdnostring‘NON_CLUSTERED’
org.quartz.scheduler.instanceIdGenerator.classnostring (class name)org.quartz.simpl .SimpleInstanceIdGenerator
org.quartz.scheduler.threadNamenostringinstanceName + ‘_QuartzSchedulerThread’
org.quartz.scheduler .makeSchedulerThreadDaemonnobooleanfalse
org.quartz.scheduler .threadsInheritContextClassLoaderOfInitializernobooleanfalse
org.quartz.scheduler.idleWaitTimenolong30000
org.quartz.scheduler.dbFailureRetryIntervalnolong15000
org.quartz.scheduler.classLoadHelper.classnostring (class name)org.quartz.simpl .CascadingClassLoadHelper
org.quartz.scheduler.jobFactory.classnostring (class name)org.quartz.simpl.PropertySettingJobFactory
org.quartz.context.key.SOME_KEYnostringnone
org.quartz.scheduler.userTransactionURLnostring (url)‘java:comp/UserTransaction’
org.quartz.scheduler .wrapJobExecutionInUserTransactionnobooleanfalse
org.quartz.scheduler.skipUpdateChecknobooleanfalse
org.quartz.scheduler .batchTriggerAcquisitionMaxCountnoint1
org.quartz.scheduler .batchTriggerAcquisitionFireAheadTimeWindownolong0
  • org.quartz.scheduler.instanceName:实例名称,用来区分特定的调度器实例。
  • org.quartz.scheduler.instanceId:实例Id,用来区分特定的调度器实例。在集群模式下,必须保证唯一。是物理上唯一,instanceName是逻辑上的区分。假如想Quartz帮生成这个值的话,可以设置为AUTO。
  • org.quartz.scheduler.instanceIdGenerator.class:调度器实例id的生成方式,只有在调度器示例id设置为Auto自动生成时有效。缺省值org.quartz.simpl.SimpleInstanceIdGenerator。
  • org.quartz.scheduler.threadName:调度器的线程名称,默认使用instanceName+’_QuartzSchedulerThread’
  • org.quartz.scheduler.makeSchedulerThreadDaemon:是否将schedule主线程设置为守护线程,默认false
  • org.quartz.scheduler.threadsInheritContextClassLoaderOfInitializer:Quartz生成的线程是否继承初始化线程的上下文类加载器,默认false
  • org.quartz.scheduler.idleWaitTime:在调度程序空闲时,重复查询是否有可用触发器的等待时间,默认30000(毫秒)
  • org.quartz.scheduler.dbFailureRetryInterval:JobStore 模式下,连接超时重试连接的间隔,默认15000(毫秒)
  • org.quartz.scheduler.classLoadHelper.class:类加载帮助类,默认org.quartz.simpl.CascadingClassLoadHelper
  • org.quartz.scheduler.jobFactory.class:指定JobFactory的类(接口)名称,负责实例化jobClass,默认值为org.quartz.simpl.PropertySettingJobFactory
  • org.quartz.context.key.SOME_KEY:代替 “scheduler context” 的一些配置。“org.quartz.context.key.MyKey = MyValue” 等价于 scheduler.getContext().put(“MyKey”, “MyValue”). 事务相关属性应该被排除在配置文件之外,除非使用的是JTA事务
  • org.quartz.scheduler.userTransactionURL:设置Quartz能够加载UserTransaction的JNDI的 URL。
  • org.quartz.scheduler.wrapJobExecutionInUserTransaction:是否在Quartz执行一个job前使用UserTransaction
  • org.quartz.scheduler.skipUpdateCheck:在程序运行前检查quartz是否有版本更新,默认false
  • org.quartz.scheduler.batchTriggerAcquisitionMaxCount:允许调度程序一次性触发的触发器数量,默认值1。1、值越大表示允许触发的任务越多;2、如果值大于1时,需要设置org.quartz.jobStore.acquireTriggersWithinLock属性为true,以避免多个触发器产生的数据混乱。
  • org.quartz.scheduler.batchTriggerAcquisitionFireAheadTimeWindow:允许触发器被获取并在其预定的触发时间之前触发的数量,默认数量为0

线程池配置

  • org.quartz.threadPool.class:线程池的实现类,一般默认使用org.quartz.simpl.SimpleThreadPool(固定大小)实例。
  • org.quartz.threadPool.threadCount:线程池中的线程数量,默认10。如果仅几个任务,建议1,如果上万个,建议50–100。
  • org.quartz.threadPool.threadPriority:线程的优先级,默认5。最小优先级1,最高10。
  • org.quartz.threadPool.makeThreadsDaemons:是否设置为守护线程,默认false。
  • org.quartz.threadPool.threadsInheritGroupOfInitializingThread:加载任务的代码的ClassLoader是否从外部继承,默认true
  • org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread
  • org.quartz.threadPool.threadNamePrefix:线程默认的前缀,默认Worker 。

如果是自定义的线程池,则可以设置自定义的属性值

org.quartz.threadPool.class = MyThreadPool
org.quartz.threadPool.attr1 = someValue  //MyThreadPool的属性attr1 的值
org.quartz.threadPool.attr2 = someValue  //MyThreadPool的属性attr2 的值

RAMJobStore

org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore

org.quartz.jobStore.misfireThreshold:最大能忍受的触发超时时间,默认值60000(毫秒),超时则认为失误。

数据连接配置

quartz框架中数据源相关的配置属性的统一前缀为:org.quartz.jobStore.

  • class,job的存储方式,可以选择存储在内存中或者持久化数据库中,默认为null

    • org.quartz.simpl.RAMJobStore 即存储在内存中,不适用配置文件时默认值
    • org.quartz.impl.jdbcjobstore.JobStoreTX 表示选择JDBC存储方式,自己管理事务
    • org.quartz.impl.jdbcjobstore.JobStoreCMT也表示JDBC,但是由全局JTA管理事务
  • driverDelegateClass,用于处理不同数据库之间差异的实现类,默认null

    • 使用mysql jdbc数据存储时设置为为org.quartz.impl.jdbcjobstore.StdJDBCDelegate
  • dataSource,配置数据源的名称,默认null

    • 如果不配置数据源名称,可以使用spring配置文件中的数据源,并在scheduler创建时注入
    • 如果此处配置了数据源的名称,可以进一步在quartz文件中配置数据源信息
    # 配置数据源名称:`dataSoruce=dataSourceName`
    org.quartz.dataSource.dataSourceName.driver
    org.quartz.dataSource.dataSourceName.URL
    org.quartz.dataSource.dataSourceName.user
    org.quartz.dataSource.dataSourceName.password
    org.quartz.dataSource.dataSourceName.maxConnections
    
  • tablePrefix,表示quartz定时任务持久化时对应的数据表前缀,默认值QRTZ_

  • misfireThreshold,最大能忍受的触发超时时间,默认值60000,超时则认为失误

  • useProperties,使用key-value的形式存储JobDataMap,默认true

    ​ 指示JDBCJobStore所有的JobDataMaps中的值都是字符串,并且能以“名字-值”对的方式存储而不是以复杂对象的序列化形式存储在BLOB字段中,应该设置为true

  • isClustered,是否以集群方式运行,默认false

    • 如果多个quartz实例使用同一个数据库,则需要设置为true,否则会报错
  • clusterCheckinInterval,检入到数据库中的频率,默认20000

  • maxMisfiresToHandleAtATime,JobStore处理未按时触发的Job数量,默认20

  • dontSetAutoCommitFalse,事务是否自动提交,默认false

  • selectWithLockSQL,配置加锁的SQL语句,默认false,需要配置时默认语句是:

    SELECT * FROM [tableName] LOCKS WHERE LOCK_NAME = ? FOR UPDATE
  • txIsolationLevelSerializable,是否使用事务隔离级别中的可序列化,默认false
  • acquireTriggersWithinLock,触发事务前是否需要拥有锁,默认true
  • lockHandler.class,用于管理数据库中相关锁机制的类名,默认null

Jdbc存储表结构

  • qrtz_blob_triggers:以blob格式存放自定义trigger信息
  • qrtz_calendars:记录quartz任务中的日历信息
  • qrtz_cron_triggers:记录cronTrigger,即cron表达式相关触发器的信息
  • qrtz_fired_triggers:存储正在触发的定时器的信息,执行完后数据清空
  • qrtz_job_details:记录每个定时任务详细信息的表
  • qrtz_locks:分布式处理时多个节点定时任务的锁信息
  • qrtz_paused_triggers_grps:存储暂停的任务触发器信息
  • qrtz_scheduler_state:记录调度器状态的表
  • qrtz_simple_triggers:记录SimpleTrigger,即普通的触发器信息
  • qrtz_simprop_triggers:存储CalendarIntervalTrigger和DailyTimeIntervalTrigger触发器信息
  • qrtz_triggers:记录每个触发器详细信息的表

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/354337.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

瑞典军事研究:从认知心理学的视角探讨军事创新进程

来源&#xff1a;Military Innovation as the Result of Mental Models of Technology 《摘要》 政治紧张局势的加剧和技术发展的进步促使Scandinavian 国家&#xff08;斯堪的纳维亚半岛&#xff0c;欧洲最大的半岛&#xff0c;有挪威、瑞典两国以及芬兰北端的一小部分。&am…

SpringBoot3集成TDengine自适应裂变存储

前言 首先很遗憾的告诉大家&#xff0c;今天这篇分享要关注才可以看了。原因是穷啊&#xff0c;现在基本都是要人民币玩家了&#xff0c;就比如chatGPT、copilot&#xff0c;这些AI虽然都是可以很好的辅助编码&#xff0c;但是都是要钱。入驻CSDN有些年头了&#xff0c;中间有几…

Python没有指针怎么实现链表?

Python没有指针怎么实现链表&#xff1f; 学习数据结构的的链表和树时&#xff0c;会遇到节点&#xff08;node&#xff09;这个词&#xff0c;节点是处理数据结构的链表和树的基础。节点是一种数据元素&#xff0c;包括两个部分&#xff1a;一个是实际需要用到的数据&#xff…

考研复试机试 | C++ | 尽量不要用python,很多学校不支持

目录1.1打印日期 &#xff08;清华大学上机题&#xff09;题目&#xff1a;代码&#xff1a;1.2改一改&#xff1a;上一题反过来问题代码&#xff1a;2.Day of Week &#xff08;上交&&清华机试题&#xff09;题目&#xff1a;代码&#xff1a;3.剩下的树&#xff08;清…

sni第三种模式复现、幽灵猫网络抓包方式复现、所有漏洞复现

sni第三种模式复现 搭建环境 [rootlocalhost nginx]# mkdir certificate [rootlocalhost nginx]# cd certificate/[rootlocalhost certificate]# openssl genrsa -des3 -out ssl.key 4096 [rootlocalhost certificate]# openssl req -new -key ssl.key -out aaa.csr [rootlo…

Django框架之模型视图-URLconf

URLconf 浏览者通过在浏览器的地址栏中输入网址请求网站对于Django开发的网站&#xff0c;由哪一个视图进行处理请求&#xff0c;是由url匹配找到的 配置URLconf 1.settings.py中 指定url配置 ROOT_URLCONF 项目.urls2.项目中urls.py 匹配成功后&#xff0c;包含到应用的urls…

ChatGPT时代,别再折腾孩子了

今天这篇完全是从两件事儿有感而发。昨天在文印店&#xff0c;在复印机上看到装订好的几页纸&#xff0c;我瞥了一眼&#xff0c;是历史知识点&#xff1a;隋朝大运河分为四段&#xff0c;分别是___ ___ ___ ___&#xff0c;连接了五大河___ ___ ___ ___ ______ 年&#xff…

开源云真机平台——Sonic应用实践

前言 Sonic是一款开源、支持分布式部署、在线自动化测试的私有云真机平台。想着写一篇总结分享。 一、云真机平台 1.云真机平台对比 目前市面上常见的云真机平台有两种&#xff0c;一种是各大服务商如阿里、腾讯、百度推出的公共云真机平台&#xff0c;如&#xff1a;WeTes…

2月18日绿健简报,星期六,农历正月廿八

2月18日绿健简报&#xff0c;星期六&#xff0c;农历正月廿八坚持阅读&#xff0c;静待花开1. 中国证监会发布全面实行股票发行注册制相关制度规则&#xff0c;即日起施行。2. 返回地面75天后神舟十四号乘组航天员首次与媒体和公众正式见面。3. 银保监会查处5家金融机构违法违规…

C语言结构体复习总结

目录 一、结构体引入 1.1 为什么要用结构体&#xff1a; 1.2 定义一个结构体&#xff1a; 1.3 结构体在声明的时候不要定义变量&#xff1a; 1.4 根据业务需求定义不同的结构体&#xff1a; 二、定义结构体和使用变量 2.1 最好不要在声明结构体时定义变量&#xff1a; …

找工作必看,用Python爬取数据分析岗位信息并可视化分析

导读&#xff1a; 最近经常收到人事小姐姐和猎头小哥哥的面试邀请&#xff0c;想想最近也不是招聘旺季呀。但又想到许多小伙伴们有找工作这方面的需求&#xff0c;今天就来分享一篇简单的爬虫案例&#xff0c;旨在跟大家一起分析一下部分招聘市场。以"数据分析"为例。…

Linux之Xshell工具使用

shell简介Xshell是一个远程工具&#xff0c;可以远程连接linux系统 &#xff0c;SSH&#xff0c;远程管理 Xshell来远程访问Linux系统的终端 。shell的英文含义是“壳”&#xff1b;它是相对于内核来说的&#xff0c;因为它是建立在内核的基础上&#xff0c;面向于用户的一种表…

Eclipse下Maven的集成

Eclipse下Maven的集成 2.1指定本地maven环境 参考&#xff1a;Eclipse的Maven创建_叶书文的博客-CSDN博客_eclipse创建maven项目 指定用本地maven指定maven仓库设置和地址2.2创建maven项目 1.新建 2.目录设置 3.坐标设置&#xff08;随便写就行&#xff09; 4.目录结构 2.3配置…

事件驱动型架构

事件驱动型架构是一种软件设计模式&#xff0c;其中微服务会对状态变化&#xff08;称为“事件”&#xff09;作出反应。事件可以携带状态&#xff08;例如商品价格或收货地址&#xff09;&#xff0c;或者事件也可以是标识符&#xff08;例如&#xff0c;订单送达或发货通知&a…

【看表情包学Linux】进程地址空间 | 区域和页表 | 虚拟地址空间 | 初识写时拷贝

&#x1f923; 爆笑教程 &#x1f449; 《看表情包学Linux》&#x1f448; 猛戳订阅 &#x1f525; &#x1f4ad; 写在前面&#xff1a;本章核心主题为 "进程地址空间"&#xff0c;会通过验证 Linux 进程的地址空间来开头&#xff0c;抛出 "同一个值能有不同内…

【IOS逆向】dumpdecrypted砸壳

【IOS逆向】dumpdecrypted砸壳 前面简单尝试了下frida-trace,发现可以追踪对应pid动态运行时的各种函数&#xff0c;但是对于一个完整APP应用&#xff0c;我们如何得到关键的运行函数&#xff0c;这里就需要对IPA进行一个逆向拆解&#xff0c;找代码逻辑&#xff0c;然后结合f…

idea同时编辑多行-winmac都支持

1背景介绍 idea编辑器非常强大&#xff0c;其中一个功能非常优秀&#xff0c;很多程序员也非常喜欢用。这个功能能够大大大提高工作效率-------------多行代码同时编辑 2win 2.1方法1 按住alt鼠标左键上/下拖动即可 这样选中多行后&#xff0c;可以直接多行编辑。 优点&a…

C++ STL 学习之【string】

✨个人主页&#xff1a; Yohifo &#x1f389;所属专栏&#xff1a; C修行之路 &#x1f38a;每篇一句&#xff1a; 图片来源 The key is to keep company only with people who uplift you, whose presence calls forth your best. 关键是只与那些提升你的人在一起&#xff0c…

前端开发常用案例(二)

这里写目录标题1.loding加载动画2.全屏加载动画效果3.吃豆豆4.鼠标悬停3D翻转效果5.3D旋转木马效果6.flex弹性布局-酷狗音乐播放列表flex弹性布局-今日头条首页热门视频栏grid网格布局-360图片展示小米商城左侧二级菜单1.loding加载动画 代码如下&#xff1a; <!DOCTYPE h…

干货 | PCB电路板短路了!试试这六种检查方法

首先&#xff0c;了解一下常见的电路板短路的种类&#xff1a;短路按照功能性可分为&#xff1a;焊接短路&#xff08;如&#xff1a;连锡&#xff09;、PCB短路&#xff08;如&#xff1a;残铜、孔偏等&#xff09;、器件短路、组装短路、ESD/EOS击穿、电路板内层微短路、电化…