Quartz is a richly featured, open source job scheduling library that can be integrated within virtually any Java application - from the smallest stand-alone application to the largest e-commerce system.java
Quartz 是一个功能丰富,开源的任务调度的库, 能够和任何Java应用整合 .git
项目地址 : github.com/quartz-sche…github
快速开始地址 : github.com/quartz-sche…spring
Demo地址 : github.com/quartz-sche…编程
public class StdSchedulerTest {
public static void main(String[] args) {
try {
//1. StdSchedulerFactory工厂机制加载一个Scheduler
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
// 2. JobBuilder 定义一个JobDetail , 工做信息
JobDetail job = JobBuilder.newJob(HelloJob.class)
.withIdentity("job1", "group1")
.build();
// 3. TriggerBuilder定义一个trigger , 触发器 , 告诉你这个Job什么时候触发
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group1")
.startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInMilliseconds(1000)
.repeatForever())
.build();
// 4.告诉Scheduler , 我这个工做须要这个trigger
scheduler.scheduleJob(job, trigger);
//5. 启动
scheduler.start();
// 这里咱们先阻塞着..
System.in.read();
// 6. 关闭
scheduler.shutdown();
} catch (SchedulerException | IOException se) {
se.printStackTrace();
}
}
}
复制代码
其中 com.example.springquartz.HelloJob
须要实现org.quartz.Job
此接口安全
public class HelloJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
JobKey key = jobExecutionContext.getJobDetail().getKey();
System.out.printf("group %s , name : %s ,\t", key.getGroup(), key.getName());
System.out.printf("Thread : %s - %s\n", Thread.currentThread().getName(), "Hello Job !");
}
}
复制代码
启动 : 日志信息 : 会告诉你任务什么时候调用的.服务器
11:12:09.682 [main] INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler 'DefaultQuartzScheduler' initialized from default resource file in Quartz package: 'quartz.properties'
11:12:09.682 [main] INFO org.quartz.impl.StdSchedulerFactory - Quartz scheduler version: 2.3.0
11:12:09.697 [main] INFO org.quartz.core.QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started.
11:12:09.697 [DefaultQuartzScheduler_QuartzSchedulerThread] DEBUG org.quartz.core.QuartzSchedulerThread - batch acquisition of 1 triggers
11:12:09.697 [DefaultQuartzScheduler_QuartzSchedulerThread] DEBUG org.quartz.simpl.PropertySettingJobFactory - Producing instance of Job 'group1.job1', class=com.example.springquartz.HelloJob
11:12:09.713 [DefaultQuartzScheduler_QuartzSchedulerThread] DEBUG org.quartz.core.QuartzSchedulerThread - batch acquisition of 1 triggers
11:12:09.713 [DefaultQuartzScheduler_Worker-1] DEBUG org.quartz.core.JobRunShell - Calling execute on job group1.job1
group group1 , name : job1 , Thread : DefaultQuartzScheduler_Worker-1 - Hello Job !
复制代码
能够经过 org.quartz.JobBuilder#usingJobData(java.lang.String, java.lang.Long)
给Job赋值参数. 对于咱们这个使用的若是是静态的数据, 好比说数据一层不变, 或者说任务先后关系不是依赖的. 能够不考虑同步问题.多线程
JobDetail job = JobBuilder.newJob(HelloJob.class)
.withIdentity("job1", "group1")
.usingJobData(HelloJob.START_TIME, System.currentTimeMillis())
.build();
复制代码
若是选择了同步, 请选择在你的Job中这俩注解 , 保持其同步关系.app
@PersistJobDataAfterExecution // 这个但愿刷新JobData,因此多线程环境下共享是安全
@DisallowConcurrentExecution // 这个保证其同步执行, 其实就是任务挨着任务.
复制代码
咱们对比使用一下. 不使用同步框架
public class HelloJob implements Job {
public static final String START_TIME = "START_TIME";
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
long start = jobExecutionContext.getMergedJobDataMap().getLong(START_TIME);
long flag = System.currentTimeMillis()-start;
System.out.printf("Thread-%d start : %s - %dms\n", tag, Thread.currentThread().getName(), System.currentTimeMillis() - start);
sleep(2000);
System.out.printf("Thread-%d end : %s - %dms\n", tag, Thread.currentThread().getName(), System.currentTimeMillis() - start);
}
}
复制代码
输出 : 因此他们并不会由于任务延时致使同步执行, 这些任务之间都是不互相依赖的.
Thread-15 start : DefaultQuartzScheduler_Worker-1 - 15ms
Thread-1002 start : DefaultQuartzScheduler_Worker-2 - 1002ms
Thread-2001 start : DefaultQuartzScheduler_Worker-3 - 2001ms
Thread-15 end : DefaultQuartzScheduler_Worker-1 - 2016ms
Thread-1002 end : DefaultQuartzScheduler_Worker-2 - 3010ms
Thread-2001 end : DefaultQuartzScheduler_Worker-3 - 4002ms
复制代码
可是, 当咱们加入了
@DisallowConcurrentExecution
@PersistJobDataAfterExecution
public class HelloJob implements Job {
public static final String START_TIME = "START_TIME";
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
long start = jobExecutionContext.getMergedJobDataMap().getLong(START_TIME);
long flag = System.currentTimeMillis()-start;
System.out.printf("Thread-%d start : %s - %dms\n", flag, Thread.currentThread().getName(), System.currentTimeMillis() - start);
sleep(2000);
System.out.printf("Thread-%d end : %s - %dms\n", flag, Thread.currentThread().getName(), System.currentTimeMillis() - start);
}
}
复制代码
输出 : 因此同步执行 ,
Thread-27 start : DefaultQuartzScheduler_Worker-1 - 28ms
Thread-27 end : DefaultQuartzScheduler_Worker-1 - 2032ms
Thread-2033 start : DefaultQuartzScheduler_Worker-2 - 2033ms
Thread-2033 end : DefaultQuartzScheduler_Worker-2 - 4034ms
复制代码
总结一下 , 他的功能性, 以及特性都十分的强. 能够保证其同步也能够不一样步, 这里就要对比一下 . ScheduledExecutorService
-> java.util.concurrent.ScheduledThreadPoolExecutor
-> java.util.concurrent.ScheduledExecutorService
他的任务调度所有是同步执行的. 第二个任务必须等待第一个任务执行完毕才行. 我后面给你们展现
他的颗粒度掌握的很是的好 .
计划任务,是任务在约定的时间执行已经计划好的工做,这是表面的意思。在Linux中,咱们常常用到 cron 服务器来完成这项工做。cron服务器能够根据配置文件约定的时间来执行特定的任务。
怎么使用? , 固然是触发器里面了 , 咱们任务调度是靠的Triggers
// 这里是每2S执行一次
Trigger trigger = TriggerBuilder.newTrigger()
.startNow()
.withSchedule(CronScheduleBuilder.cronSchedule("0/2 * * * * ?"))
.build();
复制代码
输出:
DefaultQuartzScheduler_Worker-1 : Echo com.example.springquartz.EchoJob@5f02d7f6
DefaultQuartzScheduler_Worker-2 : Echo com.example.springquartz.EchoJob@1d653213
DefaultQuartzScheduler_Worker-3 : Echo com.example.springquartz.EchoJob@7d2e9543
复制代码
其实发现Quartz框架对于每个任务对象来讲,他不是单例的, 每次都会依靠反射生成一个
简单的编程实现
SimpleScheduleBuilder.simpleSchedule()
// 2S 一次
.withIntervalInMilliseconds(2000)
// 永远执行下去
.repeatForever()
// 0 表明执行一次, 1表明执行两次
// .withRepeatCount(1)
复制代码
JobExecutionException e = new JobExecutionException("exception");
//e.refireImmediately(); // 失败了能够重复执行 , This will force quartz to run this job over and over and over and over again.
e.setUnscheduleAllTriggers(true); // 失败了立马中止trigger ,This will force quartz to shutdown this job so that it does not run again.
复制代码
这个异常须要放到 Job中抛出去, 只能抛出这个异常才能控制是否执行
Set the Trigger's priority. When more than one Trigger have the same fire time, the scheduler will fire the one with the highest priority first.
俩任务一块触发, 优先触发优先级高的任务 .
TriggerBuilder.newTrigger()
.usingJobData(EchoJob.FAVORITE_COLOR,"RED")
.forJob("JOB")
.startNow()
// 设置优先级
.withPriority(0)
.withSchedule(CronScheduleBuilder.cronSchedule("0/2 * * * * ?"))
.build();
复制代码
Instructs the Scheduler that upon a mis-fire situation, the SimpleTrigger wants to be fired now by Scheduler.
有几种, 我也不知道他这个有啥用 , 误触发.