当前位置: 首页 > news >正文

quartz使用及原理解析

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 {@Overridepublic void execute(JobExecutionContext context) throws JobExecutionException {System.out.println("任务被执行了。。。");}
}

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

public static void main(String[] args) throws Exception {// 1.创建调度器 SchedulerSchedulerFactory 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@ConditionalOnMissingBeanpublic 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@ConditionalOnMissingBeanpublic 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 {@Beanstatic 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: 10threadPriority: 5jobStore: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.QuartzAutoConfigurationif (!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:记录每个触发器详细信息的表

相关文章:

quartz使用及原理解析

quartz简介 ​ Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目&#xff0c;完全由Java开发&#xff0c;可以用来执行定时任务&#xff0c;类似于java.util.Timer。但是相较于Timer&#xff0c; Quartz增加了很多功能&#xff1a; 持久性作业 - 就是保持调度…...

Datawhale组队学习:大数据 D2——分布式文件系统(HDFS)

妙趣横生大数据 Day2三、Hadoop 分布式文件系统(HDFS)1. 分布式文件系统2. HDFS 简介3. HDFS 体系结构4. HDFS存储原理数据冗余存储数据存储策略数据错误与恢复5. HDFS数据读写过程读写过程HDFS故障类型和其检测方法HDFS编程实验1. 本地和集群文件间操作2. 基本文件操作3. Hado…...

CCIE重认证-300-401-拖图题全

拖图 拖图题 编程 snippet&#xff1b;192.168.5.0&#xff0c;mask 255.255.255.0&#xff1b;number是192.168.5.0&#xff1b;mask是255.255.255.0 snippets&#xff1b;edit-config对config&#xff0c;loopback对name 100&#xff0c;address对primary&#xff0c;mask…...

如何动态的创建类?type的其他用法?什么是元类,如何自定义元类?

1、python中一切都是对象&#xff0c;类也不例外&#xff0c;type是object的子类&#xff0c;是创建类的类。 如何动态的创建一个类&#xff1f; 用脚丫子创建 用脑子创建 不会 不知道什么事动态类 大家可能会有一堆的疑惑&#xff0c;是的我也是有很多疑惑那让我们一起来探个…...

XCP实战系列介绍15-XCP故障排查指导

本文框架 1.概述2. 通过调试器排查2.1 打开Det功能2.2 如何确定Det ErrorCode3. 通过XCP应答报文排查3.1 FE报文组成及故障码对应关系3.2 举个例子1.概述 前面几篇文章我们介绍了基于Davinci开发工具的XCP配置指导,配好了,代码也生成了,但是程序一定能正常跑起来吗?就算软…...

吉林大学软件需求分析与规范(Software Requirements Analysis Specification)

chapter0课程简介&#xff1a;◼ 软件工程专业核心课程之一◼ 软件工程课程体系最前端课程◼ 主要内容&#xff1a;需求的基本概念&#xff0c;需求的分类&#xff0c;需求工程的基本过程&#xff0c;需求获取的方法、步骤、技巧&#xff0c;需求分析和建模技术&#xff0c;需求…...

PyTorch - Conv2d 和 MaxPool2d

文章目录Conv2d计算Conv2d 函数解析代码示例MaxPool2d计算函数说明卷积过程动画Transposed convolution animationsTransposed convolution animations参考视频&#xff1a;土堆说 卷积计算 https://www.bilibili.com/video/BV1hE411t7RN 关于 torch.nn 和 torch.nn.function t…...

leetcode Day2(昨天实习有点bug,心态要崩了)

int carry 0;for(int i a.size() - 1, j b.size() - 1; i > 0 || j > 0 || carry; --i, --j) {int x i < 0 ? 0 : a[i] - 0;int y j < 0 ? 0 : b[j] - 0;int sum (x y carry) % 2;carry (x y carry) / 2;str.insert(0, 1, sum 0);}return str;加一&a…...

另一种思考:为什么不选JPA、MyBatis,而选择JDBCTemplate

以下内容转载自&#xff1a;https://segmentfault.com/a/1190000018472572 作者&#xff1a;scherman 因为项目需要选择数据持久化框架&#xff0c;看了一下主要几个流行的和不流行的框架&#xff0c;对于复杂业务系统&#xff0c;最终的结论是&#xff0c;JOOQ是总体上最好的…...

LeetCode 338. 比特位计数

给你一个整数 n &#xff0c;对于 0 < i < n 中的每个 i &#xff0c;计算其二进制表示中 1 的个数 &#xff0c;返回一个长度为 n 1 的数组 ans 作为答案。 示例 1&#xff1a; 输入&#xff1a;n 2 输出&#xff1a;[0,1,1] 解释&#xff1a; 0 --> 0 1 --> …...

排序评估指标——NDCG和MAP

在搜索和推荐任务中&#xff0c;系统常返回一个item列表。如何衡量这个返回的列表是否优秀呢&#xff1f; 例如&#xff0c;当我们检索【推荐排序】&#xff0c;网页返回了与推荐排序相关的链接列表。列表可能会是[A,B,C,G,D,E,F],也可能是[C,F,A,E,D]&#xff0c;现在问题来了…...

[Android Studio] Android Studio Virtual Device(AVD)虚拟机的功能试用

&#x1f7e7;&#x1f7e8;&#x1f7e9;&#x1f7e6;&#x1f7ea; Android Debug&#x1f7e7;&#x1f7e8;&#x1f7e9;&#x1f7e6;&#x1f7ea; Topic 发布安卓学习过程中遇到问题解决过程&#xff0c;希望我的解决方案可以对小伙伴们有帮助。 &#x1f680;write…...

kafka-3-kafka应用的核心要点和内外网访问

kafka实战教程(python操作kafka)&#xff0c;kafka配置文件详解 Kafka内外网访问的设置 1 kafka简介 根据官网的介绍&#xff0c;ApacheKafka是一个分布式流媒体平台&#xff0c;它主要有3种功能&#xff1a; (1)发布和订阅消息流&#xff0c;这个功能类似于消息队列&#x…...

VS2017+OpenCV4.5.5 决策树-评估是否发放贷款

决策树是一种非参数的监督学习方法&#xff0c;主要用于分类和回归。 决策树结构 决策树在逻辑上以树的形式存在&#xff0c;包含根节点、内部结点和叶节点。 根节点&#xff1a;包含数据集中的所有数据的集合内部节点&#xff1a;每个内部节点为一个判断条件&#xff0c;并且…...

Prometheus 记录规则和警报规则

前提环境&#xff1a; Docker环境 涉及参考文档&#xff1a; Prometheus 录制规则Prometheus 警报规则 语法检查规则 promtool check rules /path/to/example.rules.yml一&#xff1a;录制规则语法 groups 语法&#xff1a; groups:[ - <rule_group> ]rule_group…...

(API)接口测试的关键技术

接口测试也就是API测试&#xff0c;从名字上可以知道是面向接口的测试活动。所以在讲API测试之前&#xff0c;我们应该说清楚接口是什么&#xff0c;那么接口就是有特定输入和特定输出的一套逻辑处理单元&#xff0c;而对于接口调用方来说&#xff0c;不用知道自身的内部实现逻…...

快速排序算法原理 Quicksort —— 图解(精讲) JAVA

快速排序是 Java 中 sort 函数主要的排序方法&#xff0c;所以今天要对快速排序法这种重要算法的详细原理进行分析。 思路&#xff1a;首先快速排序之所以高效一部分原因是利用了离散数学中的传递性。 例如 1 < 2 且 2 < 3 所以可以推出 1 < 3。在快速排序的过程中巧…...

linux环境搭建私有gitlab仓库

搭建之前&#xff0c;需要安装相应的依赖包&#xff0c;并且要启动sshd服务(1).安装policycoreutils-python openssh-server openssh-clients [rootVM-0-2-centos ~]# sudo yum install -y curl policycoreutils-python openssh-server openssh-clients [rootVM-0-2-centos ~]…...

SpringSecurity授权

文章目录工具类使用自定义失败处理代码配置跨域其他权限授权hasAnyAuthority自定义权限校验方法基于配置的权限控制工具类 import javax.servlet.http.HttpServletResponse; import java.io.IOException;public class WebUtils {/*** 将字符串渲染到客户端** param response 渲…...

学习 Python 之 Pygame 开发坦克大战(一)

学习 Python 之 Pygame 开发坦克大战&#xff08;一&#xff09;Pygame什么是Pygame?初识pygame1. 使用pygame创建窗口2. 设置窗口背景颜色3. 获取窗口中的事件4. 在窗口中展示图片(1). pygame中的直角坐标系(2). 展示图片(3). 给部分区域设置颜色5. 在窗口中显示文字6. 播放音…...

2.5|iot冯|方元-嵌入式linux系统开发入门|2.13+2.18

一、 Linux 指令操作题&#xff08;共5题&#xff08;共 20 分&#xff0c;每小题 4分&#xff09;与系统工作、系统状态、工作目录、文件、目录、打包压缩与搜索等主题相关。1.文件1.1文件属性1.2文件类型属性字段的第1个字符表示文件类型&#xff0c;后9个字符中&#xff0c;…...

一起Talk Android吧(第四百九十六回:自定义View实例二:环形进度条)

文章目录 知识回顾实现思路实现方法示例代码各位看官们大家好,上一回中咱们说的例子是"如何使用Java版MQTT客户端",这一回中咱们说的例子是"自定义View实例二:环形进度条"。闲话休提,言归正转,让我们一起Talk Android吧! 知识回顾 看官们,我们又回…...

上传图片尺寸校验

使用方法 ● Image ● URL ● onload代码&#xff1a; async validImageSize(file, imgWidth, imgHeight) {const img new Image()img.src URL.createObjectURL(file)const { w, h } await new Promise((resolve, reject) > {img.onload () > {const { width: w, he…...

【Python】缺失值处理和拉格朗日插值法(含源代码实现)

目录&#xff1a;缺失值处理和拉格朗日插值法一、前言二、理论知识三、代码实现一、前言 对于含有缺失值的数据集&#xff0c;如果通过删除小部分记录达到既定的目标&#xff0c;那么删除含有缺失值的记录的方法是最有效的。然而&#xff0c;这种方法也有很多问题&#xff0c;…...

SpringCloudAlibaba-Sentinel

一、介绍官网&#xff1a;https://github.com/alibaba/Sentinel/下载jar包,启动,访问http://localhost:8080/创建module添加如下依赖<!--SpringCloud ailibaba sentinel --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring…...

【程序化天空盒】过程记录02:云扰动 边缘光 消散效果

写在前面 写在前面唉&#xff0c;最近筋疲力竭&#xff0c;课题组的东西一堆没做&#xff0c;才刚刚开始带着思考准备练习作品&#xff0c;从去年5月份开始到现在真得学了快一年了&#xff0c;转行学其他的真的好累&#xff0c;&#xff0c;不过还是加油&#xff01; 下面是做…...

链表OJ(三) 反转链表合集

目录 反转链表 反转链表 II 链表中的节点每k个一组翻转 描述 给定一个单链表的头结点pHead(该头节点是有值的&#xff0c;比如在下图&#xff0c;它的val是1)&#xff0c;长度为n&#xff0c;反转该链表后&#xff0c;返回新链表的表头。 数据范围&#xff1a; 0≤n≤10000≤…...

SQLSERVER2019安装步骤过程

第一步官网下载SQLSERVER软件包 目前官网只能下载最新版本2022版本。 通过迅雷下载网址 SQL Server 2019 Enterprise (x64) - DVD (Chinese-Simplified)企业版 ed2k://|file|cn_sql_server_2019_enterprise_x64_dvd_2bfe815a.iso|1632086016|58C258FF0F1D006DD3C1F5F17AF3E…...

Java模块化概述

3 模块化 3.1 模块化概述 Java语言随着这些年的发展已经成为了一]影响深远的编程语言&#xff0c;无数平台,系统都采用Java语言编写。但是&#xff0c;伴随着发展&#xff0c;Java也越来越庞大&#xff0c;逐渐发展成为-门“臃肿” 的语言。而且&#xff0c;无论是运行个大型的…...

Connext DDSPersistence Service持久性服务(2)

可选数据库组件及兼容性当Persistence Service配置为PERSISTENT模式时,您可以选择将主题数据存储在文件中还是存储在外部关系数据库中。 唯一支持的外部数据库是MySQL。 当PersistenceService在PERSISTENT模式下使用时,您可以将其配置为将DDS样本存储到关系数据库中,例如MyS…...

食品品牌推广方案/广东网站se0优化公司

IBM全球服务中心最近发布的一份白皮书描述了IBM技术研究院&#xff08;Academy of Technology&#xff09;为取得SOA实施的成功所运用的经验。具体地讲&#xff0c;他们关注于以下五个优先考虑事项&#xff1a; 以面向未来的眼光进行架构开发——对SOA实施来说&#xff0c;最需…...

研发网站要多长时间/搜索引擎优化的分类

此文是依据赵磊在【QCON高可用架构群】中的分享内容整理而成。转载请事先联系赵磊及相关编辑。 赵磊&#xff0c;Uber高级project师&#xff0c;08年上海交通大学毕业。曾就职于微软。后添加Facebook主要负责Messenger的后端消息服务。这个系统在当时支持Facebook全球5亿人同一…...

做网站源代码/百度指数网址

通过kmeans分析出租车数据并进行可视化&#xff08;1&#xff09;数据准备&#xff08;2&#xff09;创建dataframe&#xff08;3&#xff09;kmeans聚类分析&#xff08;4&#xff09;调用百度API进行数据可视化&#xff08;1&#xff09;数据准备 采用数据为出租车载客时的G…...

泾阳做网站/域名注册查询阿里云

正整数整数零正有理数有理数负整数正分数正分数有理数0分数负整数负整数负有理数负分数2、正数和负数用来表示具有相反意义的数。(二)数轴1、定义&#xff1a;规定了原点、正方向和单位长度的直线叫做数轴。2、数轴的三要素是&#xff1a;原点、正方向、单位长度。(三)相反数1、…...

亚马逊网站托管怎么做/百度统计平台

曾几何时&#xff0c;高冷的Mac用户淡淡的嘲讽了装了XX安全卫士、安全浏览器及杀毒的低贱的Windows用户。Mac OS似乎一直自带光环&#xff0c;贴着稳定、安全的标签。然而Mac OS真的永不中毒吗&#xff1f;事实真相似乎并不那么美好。Mac OS会不会中毒当然会。首先要承认的是&a…...

金坛网站建设哪家好/个人网站设计

关于推送的集成请参考这篇文章&#xff0c;本篇文章将引导你集成统计功能&#xff0c;只需要简单的三个步骤就可以集成统计功能。第一步 安装在你的项目路径下执行命令&#xff1a;npm install janalytics-react-native --savenpm install jcore-react-native --savereact-nati…...