Several ways to implement timing tasks in Java :
- Timer: java.util.Timer, a tool that comes with JDK to handle simple timing tasks
- ScheduledExecutorService: java.util.concurrent.ScheduledExecutorService, the timing task interface in JDK, can combine timing tasks with thread pool
- Scheduled: org.springframework.scheduling.annotation.Scheduled, Spring framework based on annotations to achieve timing task processing
- Quartz: An open source framework that supports distributed scheduling tasks
Quartz:
- Quartz is a powerful open source job scheduling library that can be integrated from the smallest stand-alone application to the largest e-commerce program
- Quartz can execute thousands of tasks by creating simple or complex plans
- Any task standard Java component can perform corresponding programming operations
- Quartz Scheduler supports JTA transactions and clustering
- Quartz implements a many-to-many relationship between tasks and triggers, and can associate multiple tasks with different triggers
scenes to be used
-
A task executed at a certain point in time, or a task repeated at regular intervals
-
A persistent task that maintains the scheduled state of the task
-
Task scheduling for effective management of scheduled tasks
-
Example:
- Automatically close unpaid orders for 30 minutes
- Scheduled reconciliation business with third-party companies, docking interface, etc.
- Data statistics, such as the blog system counts the number of daily fans, daily readings, etc.
- Event start notification and event end notification
- Automatic repayment setting on the 25th of each month
- Weekly or monthly reminders
Scheduler
-
Task scheduler Scheduler:
- Multiple Triggers and JobDetails can be registered in a task scheduling container
- When Trigger and JobDetail are combined, they can be scheduled by the task scheduler Scheduler
- In general, an application only needs one Scheduler object
-
SchedulerFactory is used to create Scheduler:
- Including DirectSchedulerFactory and StdSchedulerFactory
- Because the use of DirectSchedulerFactory requires a lot of detailed manual coding design, StdSchedulerFactory is generally used more
-
There are three main types of Scheduler :
- RemoteMBeanScheduler
- RemoteScheduler
- StdScheduler
Trigger
- Trigger Trigger: time rules for task scheduling
- Trigger is the trigger of Quartz , which will notify the task scheduler Scheduler to execute the specified task Job
// 指定触发器首次触发的时间
new Trigger().startAt();
// 指定触发器结束触发的时间
new Trigger().endAt();
复制代码
-
Four types of triggers are available in Quartz :
-
SimpleTrigger: It can implement a task within a specified period of time or perform multiple tasks within a period of time
-
CronTrigger:
- Calendar-based task scheduling, very powerful
- Compared with SimpleTrigger to precisely specify intervals , CronTrigger is based on Cron expressions and is more commonly used
-
DateIntervalTrigger
-
NthIncludedDayTrigger
-
-
Calendar: a collection of specific time points of some calendars
- A trigger can contain multiple Calendars, which can be used to include or exclude certain time points
JobDetail
-
Task Scheduler JobDetail:
- A concrete executable task scheduler
- Job is what this executable task scheduler will execute
- JobDetail also contains the scheme and strategy of task scheduling
-
JobDetail is bound to the specified Job. Every time the Scheduler calls to execute a Job , it first obtains the corresponding Job, then creates an instance of the Job , and then executes the content of execute() in the Job . After the task is executed, the associated Job The object instance will be released and will be cleared by the JVM 's GC
-
JobDetail provides a number of properties for Job instances:
- name
- group
- jobClass
- jobDataMap
Job
-
Task Job: Indicates the specific work to be performed or the scheduled task
- The custom task class needs to implement this interface, and define the execution logic of the task by rewriting the execute() method
-
There are two types of jobs :
-
Stateless stateless job
-
Stateful stateful job
- For the same trigger Trigger , stateful jobs cannot be executed in parallel, and the next execution can only be triggered after the last triggered task is executed.
-
-
There are two attributes of Job :
-
volatility: Indicates whether the task is persisted to database storage
-
Durability: Whether the task is retained when there is no trigger association
- Both of them indicate that the task is persisted or reserved when the value is true
- A Job can be associated with multiple Triggers, and a Trigger can only be associated with one Job
-
-
JobExecutionContext:
- The JobExecutionContext contains the Quartz runtime environment and the detailed data information of the Job itself
- When the Scheduler schedules and executes a Job , it will pass the JobExecutionContext to the execute() of the current Job , and the current Job can obtain information through the JobExecutionContext object
-
The reason why Quartz is designed as JobDetail + Job is:
- JobDetail is used to define the task data, and the real logic of executing the task is in the Job
- Because tasks may be executed concurrently, if Scheduler directly uses Job, there will be a problem of concurrent access to the same Job instance
- By binding Job with JobDetail , Scheduler will create a new Job instance according to JobDetail every time it executes , which can avoid the problem of concurrent access
SpringBoot integrates Quartz
-
Quartz uses a basic flow:
- First create the task Job, which is the main body of the task and is used to write the business logic of the task
- Then create a task scheduler Scheduler, which is used to schedule tasks, mainly for tasks such as start, stop, pause, resume, etc.
- Then create the task detail JobDetail, which is used to save task-related information, and bind to the specified task Job for execution by the scheduler
- Then create a trigger Trigger, which is used to define the trigger rules of the task. There are two main types of triggers, SimpleTrigger and CronTrigger .
- Finally, start the task JobDetail and trigger Trigger according to the trigger Scheduler
Create a task job
- Create a class to implement the task Job interface, you need to rewrite the execute() method, the content of the method is the specific business execution logic
- If it is a dynamic task, you need to dynamically pass in the parameters when creating the task detail JobDetail or trigger Trigger , and then use the JobExecutionContext to obtain the parameters for processing
Create a task scheduler Scheduler
- If it is normal, it needs to be created by the task scheduler factory SchedulerFactory
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
复制代码
- In SpringIOC , it can be injected directly through Spring :
@Autowired
private Scheduler scheduler;
复制代码
- Normal mode, created by the factory:
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();
复制代码
Create task details JobDetail
/*
* 通过JobBuilder.newJob()方法获取到当前Job的具体实现,然后通过链式调用添加任务明细
* - 固定的Job实现
* - 如果是动态实现,根据不同的类来创建Job
* - 比如((Job)Class.forName("com.oxford.job.DynamicJob").newInstance()).getClass()
* - 则当前Job的具体实现:JobBuilder.newJob(((Job)Class.forName("com.oxford.job.DynamicJob")).getClass())
*/
JobDetail jobDetail = JobBuilder.newJob(Job.class)
/*
* usingJobData可以以k-v的形式给当前JobDetail添加参数
* 可以通过链式调用usingJobData,传入多个参数
* 在Job实现类中,可以通过JobExecutionContext.getJobDetail().getJobDataMap().get("name")获取参数的值
*/
.usingJobData("name", "oxford")
// 添加认证信息
.withIdentity("name","group")
// 任务明细创建完成后,执行生效
.build()
复制代码
Create a trigger Trigger
-
Common triggers include two categories:
- SimpleTrigger
- CronTrigger
SimpleTrigger
- SimpleTrigger: Set timing execution rules according to the custom methods in the classes of the Quartz framework
Trigger trigger = TriggerBuilder.newTrigger()
/*
* usingJobData可以以k-v的形式给当前JobDetail添加参数
* 可以通过链式调用usingJobData,传入多个参数
* 在Job实现类中,可以通过JobExecutionContext.getJobDetail().getJobDataMap().get("name")获取参数的值
*/
.usingJobData("name", "oxford")
// 添加认证信息
.withIdentity("name", "group")
// 添加开始执行时间 - 立即执行startNow()
// 开始执行时间
.startAt(start)
// 结束执行时间.如果不添加这个参数表示永久执行
.endAt(end)
// 添加执行规则.使用SimpleScheduleBuilder添加SimpleTrigger触发器
.withSchedule(SimpleSchedulebuilder
.simpleSchedule()
// 执行间隔,这里是每隔6秒执行一次
.withIntervalInSeconds(6)
.repeatForever())
// 触发器创建完成.执行生效
.build();
复制代码
CronTrigger
- CronTrigger: implement triggers based on Cron expressions
Trigger trigger = TriggerBuilder.newTrigger()
/*
* usingJobData可以以k-v的形式给当前JobDetail添加参数
* 可以通过链式调用usingJobData,传入多个参数
* 在Job实现类中,可以通过JobExecutionContext.getJobDetail().getJobDataMap().get("name")获取参数的值
*/
.usingJobData("name", "oxford")
// 添加认证信息
.withIdentity("name", "group")
// 添加开始执行时间 - 立即执行startNow()
// 开始执行时间
.startAt(start)
// 结束执行时间.如果不添加这个参数表示永久执行
.endAt(end)
// 添加执行规则.使用CronScheduleBuilder添加CronTrigger触发器
withSchedule(CronScheduleBuilder
.cronSchedule("0 0/2 * * * ?"))
// 触发器创建完成.执行生效
.build();
复制代码
start task
// 根据任务明细和任务触发器添加任务
scheduler.scheduleJob(jobDetail, trigger);
if (!scheduler.isShutdown()) {
scheduler.start();
}
复制代码
suspend task
// 根据触发器中的withIdentity认证信息对任务进行暂停
scheduler.pauseTrigger(Trigger.triggerKey("name", "group"));
复制代码
recovery task
// 根据触发器中的withIdentity认证信息对任务进行恢复
scheduler.resumeTrigger(Trigger.triggerKey("name", "group"));
复制代码
delete task
// 先对任务进行暂停
scheduler.pauseTrigger(Trigger.triggerKey("name", "group"));
// 然后移除任务
scheduler.unscheduleJob(Trigger.triggerKey("name", "group"));
// 根据任务明细中的withIdentity认证信息对任务进行删除
scheduler.deleteJob(JobKey.jobKey("name", "group"));
Author: Siege Lion Chova
Link: https://juejin.cn/post/6942479525469126686
Source: Rare Earth Nuggets
The copyright belongs to the author. For commercial reprint, please contact the author for authorization, for non-commercial reprint, please indicate the source.