定时任务是经常遇到的,主要有单机定时和分布式定时。今天简单总结一下写的几个小例子。之后再总结quatz的原理,源码,其他的定时调度器等。
<dependency>
<groupId>org.quartz-schedulergroupId>
<artifactId>quartzartifactId>
<version>2.2.1version>
dependency>
<dependency>
<groupId>org.quartz-schedulergroupId>
<artifactId>quartz-jobsartifactId>
<version>2.2.1version>
dependency>
public class HelloJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("Hello Time " + LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss", Locale.CHINESE)));
}
}
public class LessonTwo {
public void run() throws Exception{
//创建调度器
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
//创建job
JobDetail jobDetail = JobBuilder.newJob(HelloJob.class).withIdentity("job2","group2").build();
//创建trigger
// Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger2","group2").startAt(DateBuilder.futureDate(1, DateBuilder.IntervalUnit.MINUTE)).build();
SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder.newTrigger().withIdentity("trigger2","group2").startAt(DateBuilder.nextGivenSecondDate(null,1)).withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(3).withRepeatCount(3)).build();
//组装调度器
scheduler.scheduleJob(jobDetail,trigger);
//打印
System.out.println("schduler says " + jobDetail.getKey() + " will run at" + trigger.getStartTime() + "interval " + trigger.getRepeatInterval()+ "repeatCount : "+ trigger.getRepeatCount());
//调度器开始
scheduler.start();
//调度器关闭
scheduler.shutdown();
}
}
trigger中可以定义什么时候触发,隔多长时间触发一次,一共触发几次。
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-txartifactId>
<version>5.0.2.RELEASEversion>
dependency>
<bean id="quartzJob1" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.hlp.myProject.job.quartzSimple.QuartzJob1"/>
<property name="jobDataAsMap">
<map>
<entry key="timeout" value="0"/>
map>
property>
bean>
<bean id="cronTrigger1" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="quartzJob1"/>
<property name="cronExpression" value="0 0/1 * * * ? *"/>
bean>
<bean id="quartzJob2" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject">
<bean class="com.hlp.myProject.job.quartzSimple.QuartzJob2"/>
property>
<property name="targetMethod" value="run"/>
<property name="concurrent" value="false"/>
bean>
<bean id="cronTrigger2" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="quartzJob2"/>
<property name="cronExpression" value="0 0/1 * * * ? *"/>
bean>
<bean id="stdScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="cronTrigger1"/>
<ref bean="cronTrigger2"/>
list>
property>
bean>
配置文件一般是定义好一个组件1,在定义另一组件2时会引用组件1,从而绑定关系。一般这种引用用的是而不是。
- job1
/**
* 基于基类的单机版定时任务
* Created by Summer on 2018-06-30.
*/
public class QuartzJob1 extends QuartzJobBean {
private Integer timeout;
public void setTimeout(Integer timeout){
this.timeout = timeout;
}
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
LocalDateTime localDateTime = LocalDateTime.now();
String s = localDateTime.format(DateTimeFormatter.ofPattern("HH:mm:ss", Locale.CHINESE));
System.out.println(s + "基于基类QuartzJobBean的任务类开始执行了");
}
}
/**
* 没有基类的单机版定时任务
* Created by Summer on 2018-06-30.
*/
public class QuartzJob2 {
public void run(){
LocalDateTime local = LocalDateTime.now();
String s = local.format(DateTimeFormatter.ofPattern("HH:mm:ss", Locale.CHINESE));
System.out.println(s + "没有基类的单机版定时任务开始执行");
}
}
<bean id="dataSourceQuartz" class="com.alibaba.druid.pool.DruidDataSource">
<property name="url" value="${db.url_quartz}"/>
<property name="username" value="${db.username}"/>
<property name="driverClassName" value="${db.driver}"/>
<property name="password" value="${db.password}"/>
<property name="maxActive" value="${db.maxActive}"/>
<property name="initialSize" value="${db.initialSize}"/>
<property name="maxWait" value="${db.maxWait}"/>
<property name="minIdle" value="${db.minIdle}"/>
<property name="timeBetweenConnectErrorMillis" value="${db.timeBetweenEvictionRunsMillis}"/>
<property name="minEvictableIdleTimeMillis" value="${db.minEvictableIdleTimeMillis}"/>
<property name="validationQuery" value="${db.validationQuery}"/>
<property name="testWhileIdle" value="${db.testWhileIdle}"/>
<property name="testOnBorrow" value="${db.testOnBorrow}"/>
<property name="testOnReturn" value="${db.testOnReturn}"/>
<property name="poolPreparedStatements" value="${db.poolPreparedStatements}"/>
<property name="maxOpenPreparedStatements" value="${db.maxOpenPreparedStatements}"/>
<property name="filters" value="stat,config"/>
<property name="defaultAutoCommit" value="false"/>
bean>
<bean id="executor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="10"/>
<property name="maxPoolSize" value="100"/>
<property name="queueCapacity" value="500"/>
bean>
<bean id="quartzJob1" class="com.hlp.myProject.job.quartzSimple.QuartzJob1" />
<bean id="testMethod2" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="durability" value="true"/>
<property name="requestsRecovery" value="true"/>
<property name="jobClass" value="com.hlp.myProject.job.quartzCluster.MyDetailQuartzJobBean"/>
<property name="jobDataAsMap">
<map>
<entry key="targetObject" value="quartzJob1"/>
<entry key="targetMethod" value="executeInternal"/>
map>
property>
bean>
<bean id="trigger1" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="testMethod2"/>
<property name="cronExpression" value="0/5 * * * * ? *"/>
bean>
<bean id="stdScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="dataSource" ref="dataSourceQuartz"/>
<property name="startupDelay" value="30"/>
<property name="applicationContextSchedulerContextKey" value="applicationKey"/>
<property name="configLocation" value="classpath:conf/quartz.properties"/>
<property name="overwriteExistingJobs" value="true"/>
<property name="autoStartup" value="true"/>
<property name="triggers">
<list>
<ref bean="trigger1"/>
list>
property>
bean>
org.quartz.scheduler.instanceName=TestScheduler1
db.driver=com.mysql.cj.jdbc.Driver
org.quartz.scheduler.instanceId=AUTO
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount=10
org.quartz.threadPool.threadPriority=5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true
org.quartz.jobStore.misfireThreshold=60000
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.tablePrefix=qrtz_
org.quartz.jobStore.maxMisfiresToHandleAtATime=10
org.quartz.jobStore.isClustered=true
org.quartz.jobStore.clusterCheckinInterval=20000
#org.quartz.dataSource.myDS.driver = com.mysql.jdbc.Driver
#org.quartz.dataSource.myDS.URL = jdbc:mysql://192.168.22.141:3306/dmsd_quartz?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
#org.quartz.dataSource.myDS.user = root
#org.quartz.dataSource.myDS.password = root
#org.quartz.dataSource.myDS.maxConnections = 30
#org.quartz.jobStore.selectWithLockSQL = SELECT * FROM {0}LOCKS WHERE LOCK_NAME = ? FOR UPDATE
/**
* quartz分布式集群 工厂类
* Created by Summer on 2018-06-30.
*/
/*
@PersistJobDataAfterExecution 添加到 Job 类后,表示 Quartz 将会在成功执行 execute() 方法后(没有抛出异常)更新 JobDetail 的 JobDataMap,下一次执行相同的任务(JobDetail)将会得到更新后的值,而不是原始的值。就像@DisallowConcurrentExecution 一样,这个注释基于 JobDetail 而不是 Job 类的实例。
@DisallowConcurrentExecution 不允许并发执行
*/
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
@Component
public class MyDetailQuartzJobBean extends QuartzJobBean implements ApplicationContextAware{
private static final Logger logger = LoggerFactory.getLogger(MyDetailQuartzJobBean.class);
private static ApplicationContext ctx;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ctx = applicationContext;
}
private String targetObject;
private String targetMethod;
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
try{
Object object = ctx.getBean(targetObject);
Method m = object.getClass().getMethod(targetMethod);
m.invoke(object);
}catch (Exception e){
e.printStackTrace();
logger.error("定时器异常",e);
}
}
public void setTargetObject(String targetMethod){
this.targetObject = targetObject;
}
public void setTargetMethod(String targetMethod){
this.targetMethod = targetMethod;
}
}
quatz与spring整合的特点是应用了配置文件,三大组件及关系都配置在了配置文件中。类中需要写的就是一个job.
运行的时候直接点击上面的运行就可以了,因为会执行配置文件中的逻辑。之前还一直疑惑没有main方法从哪里运行呢。
先定义一个任务,在定义一个触发器并把任务绑定到触发器上,然后再定义一个总的调度器,把触发器,任务都绑上去。这就是简单流程了。