preface

C: What is the saying of empty-nest youth?

Lonely to the extreme is what feeling: only QQ mailbox to wish you a happy birthday.

Teacher Zha just now also went to the QQ mailbox past mail, indeed every year from its blessing, and several years have not changed the flower.

If you fill in your birthday information on all kinds of platforms, you are probably familiar with this scene: on the day you fill in your birthday, these platforms appear more timely than your boyfriend or girlfriend. When you see them for the first time, you are suddenly overwhelmed. Is this love?

Unfortunately, no. This “favor” is “Sea King” “rain and dew even touch”, is “fish pond pond master” “cookie-cutter”. These are pre-programmed, daily, scheduled tasks that will always be on time until the server blows up.

Except, of course, for punctual birthday greetings, such scenes are not uncommon. For example, the mortgage on the 1st of each month, the spending on the 9th of each month…

In this article, We are going to introduce you to a well-known open source job scheduling framework in the Java field. With this framework, you can also do Aquaman.

Introduction to the

Quartz is another open source project in the Job Scheduler area by the OpenSymphony open source organization. It can be used in combination with J2EE and J2SE applications or on its own.

From the smallest standalone applications to the largest e-commerce systems, Quartz can be used to create simple or complex timetables to perform tens, hundreds, or even tens of thousands of jobs. [1]

Simple to use

Before using the Quartz framework, we need to understand three core concepts in Quartz.

Job: A specific work task that needs to be performed.

Trigger: Triggers the execution of a task at a specific time.

Scheduler: The person who actually performs a task, gluing tasks and triggers together, remembering that a Job can be bound to multiple triggers, but that a Trigger can only serve one Job.

Taking sending birthday wishes through QQ mailbox as an example, sending birthday wishes to users today is a Job, which is Trigger when it is executed at 9:00 every day. After understanding the concept, I will use it briefly with Teacher Zha.

Introduction of depend on

First, we create a normal Maven project and then introduce Quartz dependencies.

Teacher Zha said: 2. X series API uses Domain Specific Language (DSL) style, also can be said to be a flow/chain style (FLUENT interface). Various Builder builders.

<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.3.0</version>
</dependency>
Copy the code

Create a task

Create a class that implements the Job interface and override the Execute method of the Job interface. What you write in the execute method is exactly what you need to do.

public class SimpleJob implements Job {

    // Specific work to be performed
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        // Outputs the current thread and time
        System.out.println("SimpleJob:::" + Thread.currentThread().getName() + ": : :" + SimpleDateFormat.getDateTimeInstance().format(newDate())); }}Copy the code

When you use it, you need to bind the newly created class with JobDetail.

Teacher Zha said: this process, you don’t feel like creating a thread? Implement the Runnable interface and bind the Runnable implementation class with Thread.

// Create a task object, bind the task class, name and group it
JobDetail jobDetail = JobBuilder.newJob(SimpleJob.class)
    .withIdentity("job1"."group1")
    .build();
Copy the code

Create trigger

Once we have the task, we also need to prepare a suitable trigger for it. Since it is easy to use, let’s first create a simple trigger that will fire every 3 seconds.

// Create trigger objects. Simple triggers perform tasks every 3 seconds
Trigger trigger = TriggerBuilder.newTrigger()
    .withIdentity("trigger1"."group1")
    // Simple trigger
    .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                  .withIntervalInSeconds(3)
                  .repeatForever())
    .build();
Copy the code

Create the scheduler

Finally, we create a scheduler that binds the task to the trigger so that the task will trigger execution at the specified time.

// Create a scheduler
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
// Glue tasks and triggers
scheduler.scheduleJob(jobDetail, trigger);
// Start the scheduler
scheduler.start();
Copy the code

The complete code for simple use is as follows:

public class Test {
    
    public static void main(String[] args) throws Exception {
        // Create a task object, bind the task class, name and group the tasks
        JobDetail jobDetail = JobBuilder.newJob(SimpleJob.class)
                .withIdentity("job1"."group1")
                .build();

        // Create trigger objects. Simple triggers perform tasks every 3 seconds
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("trigger1"."group1")
                .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                        .withIntervalInSeconds(3)
                        .repeatForever())
                .build();

        // Create a scheduler
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        // Bind tasks and triggers
        scheduler.scheduleJob(jobDetail, trigger);
        // Start the scheduler
        scheduler.start();

        // Note: Quartz opens child threads, but to prevent the main thread from terminating, we set the main thread to sleep
        Thread.sleep(60000); }}Copy the code

CronTrigger

We just briefly used Quartz, where timed tasks run according to trigger Settings, but the SimpleTrigger here can only trigger periodically. And as we mentioned in the introduction, the specific time of the day or the specific time of the month to trigger, it is a little stretched.

So there is another kind of trigger called CronTrigger in Quartz, and CronTrigger can be easily implemented by Cron expression.

Cron expression

The Cron expression consists of six to seven space-separated time elements, with the seventh time element optional.

Teacher Zha said: “Second, minute, hour, day, month, week, year, these seven time elements can be accurately positioned to a certain point in time, of course, the general positioning to a certain year is very rare, so the time element of year is optional, can not specify.

location The time element permitted Special characters allowed
1 seconds 0 ~ 59 , – * /
2 points 0 ~ 59 , – * /
3 when 0 ~ 23 , – * /
4 day 1 to 31 , – *? / L W
5 month 1 to 12 or JAN to DEC , – * /
6 weeks 1 ~ 7 or SUN ~ SAT , – *? / L #
7 years Empty or 1970 ~ 2099 , – * /

What does a Cron expression look like? Let’s start with: 0, 0, 8, 14, 2? 2021, which means February 14, 2021 will be triggered at 8 a.m.

Each time element of a Cron expression can be set to a specific value, which is of course simple. In addition, let’s introduce some special characters allowed in Cron expressions.

? Question mark: used only for day and week elements, indicating that no value is specified. .

Teacher Zha said: Is it because the day of the month must be the day of the week? For example, March 10, 2021 will be a Wednesday, but April 10 will be a Saturday… . So, it’s important to remember that you can’t specify a specific value for both the day and week time elements. Will do.

* Asterisk: Can be used for all time elements to indicate each value. Example: 0 0 8 * *? It triggers at 8 am every day.

Comma: Can be used for all time elements to indicate a list. Example: 0 0 8,10,14 * *? It is triggered at 8 am, 10 am and 14 PM every day.

– Dash: Can be used for all time elements, indicating a range. Example: 0 0 8 1-3 *? This parameter is triggered at 8:00 a.m. on the 1st to 3rd of each month.

/ slash: Applies to all time elements, x/y, where x represents the starting value and y represents the increment in value. Example: 0 0 8/2 * *? It starts at 8:00 a.m. every day and triggers every two hours.

L: Applies only to the day and week elements and represents the Last value allowed on the corresponding time element (Last). Example 1:3008 L *? It triggers at 8:30 a.m. on the last day of each month. Example 2:00308? * 3L indicates the Tuesday of the last week of each month.

Teacher Zha said: Because the foreign week starts from Sunday, the number of Sunday means 1, so in the example, 3 of 3L means Tuesday.

W: Used only for the day element and represents the last working day of the specified date. Example: 0 0 8 10W *? It triggers at 8am on the 10th of each month, but if the 10th is not a working day then the nearest working day is chosen. The 10th is Saturday, so make it Friday; The 10th is Sunday, so call it Monday.

There is a special case: set to 1W. If 1st is not a working day, even if 1st is Saturday, it will not execute on Friday of last month, but on Monday of this month.

Teacher Zha said: many scheduled tasks need to be performed during the working day, so it is understandable to have such a symbol to indicate the meaning of this. L and W can also be used together on day elements, for example: * * * LW *? This parameter is triggered on the last working day of the month.

# : used only for the week element, x#y, where y represents the week of the month and x represents the day of the week. Example: 0 0 8? * 3#2: Triggered on Tuesday of the second week of each month at 8am.

Are you dizzy? Here are some common Cron expressions for you.

Cron expression meaning
0, 0, 2, 1 star? 2 a.m. on the first of every month
0 to 15 10? * MON-FRI 10:15 a.m., Monday through Friday
0 0/30 9-17 * *? Every half hour during your 9-5 working hours
0 15 10 L * ? 10:15 a.m. on the last day of the month
0 to 15 10? * 6L 10:15 a.m. on the last Friday of every month
0 to 15 10? * 6 # 3 Third Friday of every month at 10:15 a.m
0 to 10, 44 14? 3 WED Every Wednesday in March at 2:10 and 2:44 p.m

Cron expressions are not only used in the Quartz framework, but are also used in many tools related to timed tasks, so it is important to be proficient in writing Cron expressions.

There are a number of online Cron expression generators (Resources [3] are the ones he recommends) that can be visually selected to automatically generate Cron expressions and provide test execution.

Case implementation

Now that we know about Cron expressions, let’s use Cron expressions to implement the example we just described.

public class Test2 {
    
    public static void main(String[] args) throws Exception {
        // Create a task object, bind the task class, name and group the tasks
        JobDetail jobDetail = JobBuilder.newJob(SimpleJob.class)
                .withIdentity("job1"."group1")
                .build();

        // Create a trigger object that executes a task every 3 seconds using a Cron expression
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("trigger1"."group1")
                .withSchedule(CronScheduleBuilder.cronSchedule("0/3 * *? * *"))
                .build();

        // Create a scheduler
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        // Bind tasks and triggers
        scheduler.scheduleJob(jobDetail, trigger);
        // Start the scheduler
        scheduler.start();

        // Quartz starts the child thread, and to prevent the main thread from terminating, we set the main thread to sleep
        Thread.sleep(60000); }}Copy the code

Spring integration of the Boot

How could Spring, the top streaming framework in the Java world, not provide integration for Quartz? However, native Spring integration of Quartz configuration files is a headache, so let’s use Spring Boot to implement Quartz integration.

Introduction of depend on

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
Copy the code

Create a task

@Component
public class SimpleJob extends QuartzJobBean {
    
    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        // Outputs the current thread and time
        System.out.println("SimpleJob:::" + Thread.currentThread().getName() + ": : :" + SimpleDateFormat.getDateTimeInstance().format(newDate())); }}Copy the code

The Job interface is the same as QuartzJobBean. Because QuartzJobBean implements the Job interface.

public abstract class QuartzJobBean implements Job {... }Copy the code

Write the configuration

Create a configuration class that provides two Bean configurations for the task and trigger, and remember to specify the task for the trigger.

@Configuration
public class SchedulerConfig {

    / / task bean
    @Bean
    public JobDetail simpleJobBean(a) {
        return JobBuilder.newJob(SimpleJob.class)
                .withIdentity("job1"."group1")
                // Jobs added with no trigger must be durable.
                .storeDurably()
                .build();
    }

    // Trigger bean
    @Bean
    public Trigger simpleTrigger(a) {
        return TriggerBuilder.newTrigger()
                .withIdentity("trigger1"."group1")
                .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                        .withIntervalInSeconds(3)
                        .repeatForever())
                // Specify specific tasks.forJob(simpleJobBean()) .build(); }}Copy the code

Spring Task

Spring provides Spring Task starting with 3.x, which can be understood as a lightweight Quartz. Next, let’s try it out in Spring Boot.

To create a Spring Boot project, you don’t need to add any extra dependencies. In any Spring component, create a normal method to write a task (you can write more than one), specify Cron expressions for it via the @scheduled annotation, and you have a task bound to triggers.

@Component
public class TestTask {
    
    @Scheduled(cron = "0/3 * * ? * * ")
    public void task1(a) {
        System.out.println("Current time is:"+ LocalDateTime.now()); }}Copy the code

Finally, use @enablesCheduling to enable the task scheduling function on the launcher/task class.

@EnableScheduling // Enable task scheduling
@SpringBootApplication
public class DemoSpringbootApplication {

    public static void main(String[] args) { SpringApplication.run(DemoSpringbootApplication.class, args); }}Copy the code

The resources

[1]Quartz: www.quartz-scheduler.org/

[2] GitHub address: github.com/quartz-sche…

[3]MaTools online Cron expression generator: www.matools.com/cron

Afterword.

C: Well, that concludes our introduction to the Quartz timer. The RAMJobStore model of Quartz stores Trigger and Job in memory, which is fast, but the problem is that it can’t persist.

As a result, Quartz also has a JDBC JobStore mode, where Quartz uses JDBC to store triggers and jobs in the database. Clusters that want to implement Quartz also need to complete this step first.

Of course, there are many implementations of timers in Java. For example, Java. Util. The Timer, ScheduledThreadPoolExecutor (based on the timing of the thread pool design task class), delay queue, etc., are interested can go to understand. Otherwise, we can introduce you later when Mr. Cha has time.