QuartzRAM
Quartz是一个完全由java编写的开源作业调度框架,这里只写基于RAM的,相信你看完本篇,你就学会应用Quartz了,至于持久化应用,我会写在另一篇里,如果对笔者文章或者其他地方有见解或者疑问请下方评论或者至liruli@aliyun.com
1.QuartzRAMDemo
状态控制:
启动:start();
暂停:standby();
停止:shutdown();
注意: 使用shutdown()方法后必须重新实例化,否则无法启动;只有当scheduler启动后,即使
处于暂停状态也不行,trigger才会被触发(job才会被执行)。
JobDemo
public class JobDemo implements Job {
@Override
public void execute(JobExecutionContext arg0) throws JobExecutionException {
// TODO Auto-generated method stub
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = format.format(new Date());
System.out.println(time + " helloword!!");
}
}
执行一次的定时任务
public static void testJob() throws SchedulerException{
//quartz工厂类
SchedulerFactory factory = new StdSchedulerFactory();
//get调度器
Scheduler scheduler = factory.getScheduler();
scheduler.start();
//scheduler.standby();
JobDetail job = newJob(JobDemo.class).build();//定时执行的工作
//得到jobKey
JobKey jobKey = job.getKey();
int limit_time = 5;
//定时设置
SimpleTrigger trigger = (SimpleTrigger) newTrigger()
.startAt(futureDate(limit_time, IntervalUnit.SECOND))//秒
.withSchedule(SimpleScheduleBuilder.simpleSchedule())
.forJob(jobKey)
.build();
scheduler.scheduleJob(job, trigger);
//停止
//scheduler.shutdown();
}
自定义执行次数
public static void test1Job() throws SchedulerException {
SchedulerFactory factory = new StdSchedulerFactory();
Scheduler scheduler = factory.getScheduler();
JobDetail job = newJob(JobDemo.class)
.withIdentity("myJob", "group1")//定义的job 名称 组名
.build();
//任务运行的时间,SimpleSchedle类型触发器有效
/* long time= System.currentTimeMillis() + 3*1000L; //3秒后启动任务
Date statTime = new Date(time);*/
//创建触发器
SimpleScheduleBuilder simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule();
simpleScheduleBuilder.withIntervalInSeconds(10);//以秒为单位
simpleScheduleBuilder.withRepeatCount(5);//执行次数
Trigger trigger = TriggerBuilder.newTrigger()
//.withDescription("")描述
//.withIdentity("ramTrigger", "ramTriggerGroup") 触发器的名称 触发器的组
//.startAt(statTime) //默认当前时间启动
//.withSchedule(CronScheduleBuilder.cronSchedule("0/2 * * * * ?")) //两秒执行一次 corn自定义表达式http://cron.qqe2.com/
.withSchedule(simpleScheduleBuilder) // 这里用触发器
.build();
// 任务放入调度器
scheduler.scheduleJob(job, trigger);
scheduler.start();
}
2.Quartz传参问题
JobDataMap是Java Map接口的一个实现,额外增加了一些便于存取基本类型的数据的方法;在job实例执行的时候,可以使用其中的数据;
getJobDataMap
首先得到JobDataMap,然后存键值对:
//得到job
JobDetail job = newJob(JobDemo.class).build();
//得到JobDataMap
JobDataMap jobDataMap = job.getJobDataMap();
jobDataMap.put("name", "张三");
jobDataMap.put("age", "18");
jobDataMap.put("sex", "男");
job接收
public class JobDemo implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
//得到jobDataMap
JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
String name = (String) jobDataMap.get("name");
String age = (String) jobDataMap.get("age");
String sex = (String) jobDataMap.get("sex");
//想干点啥就干点啥
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = format.format(new Date());
System.out.println(time + " helloword!!" + "\n姓名:" + name + "\n年龄:" + age + "\n性别:" + sex);
}
3.Job线程并发问题
quartz默认是多线程的,如果执行任务的对象不是单例的,则每个线程都会产生任务对象,这些任务对象的同时执行可能会导致并发问题
@DisallowConcurrentExecution 禁止并发执行多个相同定义的JobDetail, 这个注解是加在Job类上的, 但意思并不是不能同时执行多个Job, 而是不能并发执行同一个Job Definition(由JobDetail定义), 但是可以同时执行多个不同的JobDetail
4.重启恢复策略
quartz,java世界里面的任务管理容器。
至于为什么会有misfire这个概念,我想可以重这三个方面来进行说明:
1 所有的线程都在忙于更高优先级的任务
2 任务本身CRASH了
3 代码的BUG,导置错误的设置了JOB
基于这3种原因,其实也是现实世界中的常理。没有任何事情,都能保证100%运行OK。quartz提出了misfire的理论,让任务在错过之后,还能正常的运行。
misfire策略:
使用方法:
public static void testJob() throws SchedulerException{
//quartz工厂类
SchedulerFactory factory = new StdSchedulerFactory();
//get调度器
Scheduler scheduler = factory.getScheduler();
scheduler.start();
//scheduler.standby();
JobDetail job = newJob(JobDemo.class).build();//定时执行的工作
//得到jobKey
JobKey jobKey = job.getKey();
int limit_time = 5;
//定时设置
SimpleTrigger trigger = (SimpleTrigger) newTrigger()
.startAt(futureDate(limit_time, IntervalUnit.SECOND))//秒
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withMisfireHandlingInstructionIgnoreMisfires())//线程重启恢复策略
.forJob(jobKey)
.build();
scheduler.scheduleJob(job, trigger);
//停止
//scheduler.shutdown();
}
//在触发器中定义也可
SimpleScheduleBuilder simpleScheduleBuilder = SimpleScheduleBuilder.simpleSchedule();
simpleScheduleBuilder.withIntervalInSeconds(10);//以秒为单位
simpleScheduleBuilder.withRepeatCount(5);//执行次数
simpleScheduleBuilder.withMisfireHandlingInstructionIgnoreMisfires();