在程序开发过程中,我们经常需要使用到定时任务,java自带的Timer类虽然能够实现定时任务,但功能较有限,同时遇到异常的时候会停止所有任务。
这里介绍一个功能更加强大的任务调度器quartz:
步骤:
1、引入quartz和slf4j-api两个jar包:
可到下面地址下载对应jar包
quartz-2.3.0.jar:http://mvnrepository.com/artifact/org.quartz-scheduler/quartz/2.3.0
slf4j-api-1.7.25.jar:http://mvnrepository.com/artifact/org.slf4j/slf4j-api/1.7.25
2、创建定时任务类:
该类需要实现 Job 接口并重写 execute 方法,该方法即为定时任务所执行的内容。
在该方法中,我们可以通过传入的 JobExecutionContext 参数获取调用该定时任务的 JobDetail 对象,从而获取传给该任务的变量。
另外我们还能通过 JobExecutionContext 获取该定时任务调度器 Scheduler,从而控制定时任务的暂停、终止等状态
3、创建启动定时任务的类:
(1)创建 JobDetail 对象,同时加入需要传递给定时任务的变量
(2)创建 Trigger 对象,同时定义定时任务执行的时间间隔以及执行次数等信息
(3)创建调度器 Scheduler ,用来绑定 JobDetail和 Trigger,最后通过调度器启动定时任务
例子:创建一个定时任务,该定时任务每3秒执行一次,并且一直重复执行,当满足一定条件后停止该定时任务
1、定时任务执行的类
public class task implements Job{
private static Scheduler scheduler = null;
@Override
public void execute(JobExecutionContext context) throws JobExecutionException
{
//通过context.getJobDetail().getJobDataMap()可获取JobDetail对象传过来的JobDataMap,再通过get方法获取某个key对应的value
String ab = (String) context.getJobDetail().getJobDataMap().get("ab");
boolean cd = (boolean) context.getJobDetail().getJobDataMap().get("cd");
//通过context.getJobDetail().getJobDataMap().getInt("number")可获取JobDetail对象传过来的Integer类型且key为"number"对应的value
int num = context.getJobDetail().getJobDataMap().getInt("number");
//获取调度器 ,从而控制该定时任务状态
scheduler = context.getScheduler();
System.out.println("ab : " + ab + ", cd : " + cd + ", number : " + num);
//可在这里调用某个方法修改num的值来控制定时任务状态
if(num == 10)
{
try {
scheduler.shutdown();
} catch (SchedulerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//若上面执行到 scheduler.shutdown() 停止定时任务,程序仍会执行到这一句才终止,即可以确定任务停止的具体位置
System.out.println("ab : " + ab + ", cd : " + cd + ", number : " + num);
}
}
2、启动定时任务的类:
public class test{
private static Scheduler scheduler = null;
public static void main(String[] args)
{
// 实例JobDataMap对象,以key:value方式加入需要传给定时任务的参数,value可以为任意对象
JobDataMap jobDataMap = new JobDataMap();
jobDataMap.put("ab", "hello");
jobDataMap.put("cd", false);
// 创建JobDetail,通过newJob():方法绑定定时任务对应的类;withIdentity():方法设定身份标识,可自行定义;
// 使用 usingJobData():传递变量给定时任务,既可以使用JobDataMap传递一个map对象,也可以以key,value形式传递变量
// 最后需要调用build():方法实例化JobDetail对象
JobDetail jobDetail = JobBuilder.newJob(task.class).withIdentity("job").usingJobData(jobDataMap)
.usingJobData("number", 3).build();
// 创建Trigger,withIdentity():方法设定身份标识,可自行定义;
// withIntervalInSeconds():定义定时任务执行的间隔;repeatForever():让定时任务一直重复执行
int seconds = 3;
SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder.newTrigger().withIdentity("mytrigger")
.startNow().withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(seconds).repeatForever()).build();
try
{
// 创建调度器,绑定JobDetail和Trigger
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
scheduler = schedulerFactory.getScheduler();
scheduler.scheduleJob(jobDetail, trigger);
// 启动定时任务
scheduler.start();
// 关闭定时任务 scheduler.shutdown();
// 暂停定时任务 scheduler.standby();
}
catch (SchedulerException e)
{
// LOG.error(...);
}
}
}