1.在最近的实际开发项目中,开发了一段定时任务处理逻辑,然后不太明白里面的原理,就查询资料和个人理解。见下代码,主要有两个类,第一个类是实现了Job的quartz定时任务类;第二个就是创建任务调度并且启动所有定时执行任务类。
(1)主要jar包,引入quartz-1.6.0.jar;无配置文件quartz.properties。
注意:当我们在我们的项目中添加了quartz.properties的时候,我们需要把那些我们不需要修改的配置也加上,并不能只有我们修改的配置。因为通过查看源代码我们可以知道,调度器在初始化的时候,首先判断我们是否有quartz.properties,如果有的话,就是用我们系统中的配置文件,否则就从jar包里加载quartz.properties进行默认的初始化。
配置文件如下:
我们需要copy一份这个属性文件,并在这个文件的基础上修改线程池的配置:
#可以是任何正整数,虽然你应该意识到只有1到100之间的数字是非常实用的。这是可用于并发执行作业的线程数。如果你只有几个工作每天发射几次,那么1个线程是很多!如果你有成千上万的工作,每分钟都有很多工作,那么你可能希望一个线程数可能更多的是50或100(这很重要,取决于你的工作所执行的工作的性质,以及你的系统资源!)。
#===============================================================
#配置文件不是必须的,Quartz对配置项都是有默认值的,当需要自定义的时候,
#可以在classpath路径下放一个quartz.properties文件,Quartz的StdSchedulerFactory
#在启动时会自动加载该配置文件。
#===============================================================
#===============================================================
#1.配置主调度程序的属性
#===============================================================
org.quartz.scheduler.instanceName = DefaultQuartzScheduler
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false
org.quartz.scheduler.wrapJobExecutionInUserTransaction = false
#当检查某个Trigger应该触发时,默认每次只Acquire(获得)一个Trigger,(为什么要有Acquire的过程呢?是为了防止多线程访问的情况下,同一个Trigger被不同的线程多次触发)。尤其是使用JDBC JobStore时,一次Acquire就是一个update语句,尽可能一次性的多获取几个Trigger,一起触发,当定时器数量非常大的时候,这是个非常有效的优化。当定时器数量比较少时,触发不是极为频繁时,这个优化的意义就不大了。
org.quartz.scheduler.batchTriggerAcquisitionMaxCount=50
#===============================================================
#2.配置线程池的属性
#===============================================================
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
#线程池里的线程数,默认值是10,当执行任务会并发执行多个耗时任务时,要根据业务特点选择线程池的大小。可用于并发执行作业的线程数
org.quartz.threadPool.threadCount = 10
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
#===============================================================
#3.配置JobStore的属性
#===============================================================
org.quartz.jobStore.misfireThreshold = 60000
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
1.配置主调度程序的属性
分别设置调度器的实例名(instanceName) 和实例 ID (instanceId)。属性 org.quartz.scheduler.instanceName 可以是你喜欢的任何字符串。默认名字一般都采用QuartzScheduler
2.配置线程池的属性
这些线程在 Quartz 中是运行在后台担当重任的。threadCount 属性控制了多少个工作者线程被创建用来处理 Job。原则上是,要处理的 Job 越多,那么需要的工作者线程也就越多。threadCount 的数值至少为 1。Quartz 没有限定你设置工作者线程的最大值,但是在多数机器上设置该值超过100的话就会显得相当不实用了,特别是在你的 Job 执行时间较长的情况下。这项没有默认值,所以你必须为这个属性设定一个值。
threadPriority 属性设置工作者线程的优先级。优先级别高的线程比级别低的线程更优先得到执行。threadPriority 属性的最大值是常量 java.lang.Thread.MAX_PRIORITY,等于10。最小值为常量 java.lang.Thread.MIN_PRIORITY,为1。这个属性的正常值是 Thread.NORM_PRIORITY,为5。大多情况下,把它设置为5,这也是没指定该属性的默认值。
最后一个要设置的线程池属性是 org.quartz.threadPool.class。这个值是一个实现了 org.quartz.spi.ThreadPool 接口的类的全限名称。Quartz 自带的线程池实现类是 org.quartz.smpl.SimpleThreadPool,它能够满足大多数用户的需求。这个线程池实现具备简单的行为,并经很好的测试过。它在调度器的生命周期中提供固定大小的线程池。你能根据需求创建自己的线程池实现,如果你想要一个随需可伸缩的线程池时也许需要这么做。这个属性没有默认值,你必须为其指定值。
创建Scheduler定时任务步骤
1.创建任务
2.创建触发器
3.创建调度器
4.将任务及其触发器放入调度器
5.调度器开始调度任务
创建要被定执行的任务类
【1】这一步只需要创建一个实现了org.quartz.Job接口的类,并实现这个接口的唯一一个方法execute(JobExecutionContext arg0) throws JobExecutionException即可。如
package com.fync.quartz;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
/**
* 创建要被定执行的任务类
* @author long
*
*/
public class MyJob implements Job{
public void execute(JobExecutionContext context)
throws JobExecutionException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
System.out.println(sdf.format(new Date()));
//处理定时任务过渡表,到达交易开始时间,处理挂单业务
}
}
【2】创建任务调度,并执行
Scheduler 核心概念
- 调度器 Scheduler
- 任务 JobDetail,一个job对应多个tigger
- 触发器 trigger
package test;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
/**
* 创建任务调度,并执行
*/
public class MainScheduler {
public static void schedulerJob() throws SchedulerException{
/**
* //1.创建调度器 SchedulerFactory 是一个接口,用于Scheduler的创建和管理
SchedulerFactory schedFact = new SchefulerFactory();
Scheduler scheduler = schedFact.getScheduler();
//2.调度器开始调度任务
scheduler.start();
//3.创建任务。参数分别是任务的名(唯一的),任务的组,需要执行的任务class,这个class必须是实现quartz.的job接口,接口下的execute方法就是执行的任务
JobDetail jobDetail = new JobDetail("TransTaskRecivweThread","GROUP_1",MyJob.class);
//4.创建触发器 时间格式 [秒] [分] [小时] [日] [月] [周] [年]
CronTrigger trigger = new CronTrigger("TransTaskRecivweThread","GROUP_1");
//每分钟执行一次。
trigger.setCronExpression("0 0/"+minute+" * * * ? *");
//5.将任务及其触发器放入调度器。绑定 jobDetail 和 trigger,将它注册进 Scheduler 当中 ,返回值是最近一次任务执行的开始时间
scheduler.schedulerJob(jobDetail,trigger);
System.out.println("declare任务线程开启");
*
*/
//1.创建任务
JobDetail jobDetail = JobBuilder.newJob(MyJob.class).withIdentity("job1", "group1").build();
//2.创建触发器 每3秒钟执行一次
Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group3")
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(3).repeatForever())
.build();
//3.创建调度器
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
//4.将任务及其触发器放入调度器
scheduler.scheduleJob(jobDetail, trigger);
//5.调度器开始调度任务
scheduler.start();
}
public static void main(String[] args) throws SchedulerException {
MainScheduler mainScheduler = new MainScheduler();
mainScheduler.schedulerJob();
}
}
【3】scheduler的主要函数
// 绑定 jobDetail 和 trigger,将它注册进 Scheduler 当中 ,返回值是最近一次任务执行的开始时间
Date scheduleJob(JobDetail jobDetail, Trigger trigger)
// 启动 Scheduler
void start()
// 暂停 Scheduler
void standby()
// 关闭 Scheduler
void shutdown()