Before I get into the main body, I want to introduce all the scheduled tasks that Java can implement, which is actually the underlying implementation idea.

Contents of this tutorial:

  1. A thread waits to implement a scheduled task
  2. Use Timer to implement scheduled tasks
  3. ScheduledExecutorService is used to implement scheduled tasks
  4. Quartz timed task framework standalone application
  5. Scheduled spingboot2 integration
  6. Spingboot2 integrates the Quartz framework to persist scheduled tasks

###1. Threads wait to implement scheduled tasks

package com.fantj.myScheduled;

/**
 * Created by Fant.J.
 */
public class Test {
    public static void main(String[] args) {
        Thread thread = new Thread(()->{
            while (true) {
                System.out.println("Let's say I'm a timed task."); try { Thread.sleep(1000 * 10); Catch (InterruptedException e) {e.printStackTrace(); }}}); }}Copy the code

As you can see from the code, if the task is complex, it is quite troublesome, and there is a risk of memory leakage, and it is out of control.

Now let’s do a relatively simple one.

###2. Timer

package com.fantj.myScheduled;

import java.util.Timer;
import java.util.TimerTask;

/**
 * Created by Fant.J.
 */
public class Test {
    public static void main(String[] args) {

        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                System.out.println("TimerTask is called!"); }}; Timer timer = new Timer(); /* * Parameters: 1, task body 2, delay time (can specify execution date) 3, task execution interval */ timer.schedule(task, 0, 1000 * 3); timer.scheduleAtFixedRate(task, 0, 1000 * 3); }}Copy the code

Note the two methods called by timer above: 2. ScheduleAtFixedRate. If the first execution is delayed, the execution time of subsequent tasks is based on the execution time of the last task (synchronization needs to be considered).

If I have to be rude, the first one is to wait until the task is finished, and the second one is to start timing when the task is running.

Let’s take a quick look at the underlying implementation of Timer

public void schedule(TimerTask task, Date firstTime, long period) {
        if (period <= 0)
            throw new IllegalArgumentException("Non-positive period.");
        sched(task, firstTime.getTime(), -period);
    }
Copy the code

Then look at the TimerTask class

public abstract class TimerTask implements Runnable { public abstract void run(); . }Copy the code

It can probably be seen that this is also a thread implementation.

######Timer also has disadvantages:

When multiple threads process timed tasks in parallel, when a Timer runs multiple timeTasks, other tasks are automatically terminated as long as one of them does not catch an exception. ScheduledExecutorService does not have this problem.

###3. Let’s study ScheduledExecutorService

package com.fantj.myScheduled;

/**
 * Created by Fant.J.
 */
public class Test {
    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("ScheduledExecutorService Task is called!"); }}; ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor(); / / parameters: 1, task 2, performed for the first time delay / / 3, task execution time interval of 4, time interval unit service. ScheduleAtFixedRate (runnable, 0, 3, TimeUnit. SECONDS); }}Copy the code

This.. Executors thread pool appears.

If you look closely at the previous implementation cases, none of the timed tasks are controllable, which is particularly unfriendly to developers. JobDetail is the logic for writing timed tasks. Trigger is a Trigger used to define cron and the number of times it is executed.

    String getSchedulerName() throws SchedulerException;

    String getSchedulerInstanceId() throws SchedulerException;

    SchedulerContext getContext() throws SchedulerException;

    void start() throws SchedulerException;

    void startDelayed(int var1) throws SchedulerException;

    boolean isStarted() throws SchedulerException;

    void standby() throws SchedulerException;

    boolean isInStandbyMode() throws SchedulerException;

    void shutdown() throws SchedulerException;

    void shutdown(boolean var1) throws SchedulerException;

    boolean isShutdown() throws SchedulerException;

    SchedulerMetaData getMetaData() throws SchedulerException;

    List<JobExecutionContext> getCurrentlyExecutingJobs() throws SchedulerException;

    void setJobFactory(JobFactory var1) throws SchedulerException;

    ListenerManager getListenerManager() throws SchedulerException;

    Date scheduleJob(JobDetail var1, Trigger var2) throws SchedulerException;

    Date scheduleJob(Trigger var1) throws SchedulerException;

    void scheduleJobs(Map<JobDetail, Set<? extends Trigger>> var1, boolean var2) throws SchedulerException;

    void scheduleJob(JobDetail var1, Set<? extends Trigger> var2, boolean var3) throws SchedulerException;

    boolean unscheduleJob(TriggerKey var1) throws SchedulerException;

    boolean unscheduleJobs(List<TriggerKey> var1) throws SchedulerException;

    Date rescheduleJob(TriggerKey var1, Trigger var2) throws SchedulerException;

    void addJob(JobDetail var1, boolean var2) throws SchedulerException;

    void addJob(JobDetail var1, boolean var2, boolean var3) throws SchedulerException;

    boolean deleteJob(JobKey var1) throws SchedulerException;

    boolean deleteJobs(List<JobKey> var1) throws SchedulerException;

    void triggerJob(JobKey var1) throws SchedulerException;

    void triggerJob(JobKey var1, JobDataMap var2) throws SchedulerException;

    void pauseJob(JobKey var1) throws SchedulerException;

    void pauseJobs(GroupMatcher<JobKey> var1) throws SchedulerException;

    void pauseTrigger(TriggerKey var1) throws SchedulerException;

    void pauseTriggers(GroupMatcher<TriggerKey> var1) throws SchedulerException;

    void resumeJob(JobKey var1) throws SchedulerException;

    void resumeJobs(GroupMatcher<JobKey> var1) throws SchedulerException;

    void resumeTrigger(TriggerKey var1) throws SchedulerException;

    void resumeTriggers(GroupMatcher<TriggerKey> var1) throws SchedulerException;

    void pauseAll() throws SchedulerException;

    void resumeAll() throws SchedulerException;

    List<String> getJobGroupNames() throws SchedulerException;

    Set<JobKey> getJobKeys(GroupMatcher<JobKey> var1) throws SchedulerException;

    List<? extends Trigger> getTriggersOfJob(JobKey var1) throws SchedulerException;

    List<String> getTriggerGroupNames() throws SchedulerException;

    Set<TriggerKey> getTriggerKeys(GroupMatcher<TriggerKey> var1) throws SchedulerException;

    Set<String> getPausedTriggerGroups() throws SchedulerException;

    JobDetail getJobDetail(JobKey var1) throws SchedulerException;

    TriggerState getTriggerState(TriggerKey var1) throws SchedulerException;

    void resetTriggerFromErrorState(TriggerKey var1) throws SchedulerException;

    boolean interrupt(String var1) throws UnableToInterruptJobException;

    boolean checkExists(JobKey var1) throws SchedulerException;

Copy the code

As you can see, the control over scheduled tasks is pretty complete. Including add, delete, change, check, etc. The following is an example, of course, you need to download the necessary dependency jar, this can be baidu download, not focus on the explanation.

package com.fantj.myScheduled;

/**
 * Created by Fant.J.
 */
public class Test {
    public static void main(String[] args) {
        try {
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
            scheduler.start();

            JobDetail job = JobBuilder.newJob(Job.class)
                    .withIdentity("job"."group").build(); / / sleep duration can be specified unit of time, as used here second unit (withIntervalInSeconds) SimpleTrigger trigger = TriggerBuilder. NewTrigger () withIdentity ("trigger"."group").startNow()
                    .withSchedule(simpleSchedule().withIntervalInSeconds(3).repeatForever())
                    .build();

            scheduler.scheduleJob(job, trigger);

            // scheduler.shutdown();

        } catch (SchedulerException se) {
            se.printStackTrace();
        }
    }
}

    class Job implements org.quartz.Job {
        @Override
        public void execute(JobExecutionContext context) throws JobExecutionException {
            System.out.println("Quartz task is called!"); }}Copy the code

Scheduled spingboot2 integration

SpringBoot has built-in Scheduled tasks and is extremely easy to operate. This can be achieved by importing the spring-boot-starter-Web dependency package.

The first step in Scheduled

Add the @enablesCheduling annotation to the bootstrap class

package com.fantj;

@SpringBootApplication
@MapperScan("com.fantj.mapper"Public class MybatisApplication {public static void main(String[] args) { SpringApplication.run(MybatisApplication.class, args); }}Copy the code
The second step Scheduled

Writing Task. That is, scheduled tasks.

package com.fantj.myScheduled; /** * Scheduled * Created by fant.j. */ @component public class Task {@scheduled (cron = scheduled)"5 0 0 * *?")
    public void scheduledTask1(){
        System.out.println("scheduledTask method run..");
    }

    @Scheduled(initialDelay =  1000 * 10,fixedDelay = 1000 * 5)
    public void scheduledTask2(){
        System.out.println("scheduledTask method run..");
    }

    @Scheduled(initialDelay =  1000 * 10,fixedDelay = 1000 * 5)
    public void test() throws Exception {
        for(int i = 0; i<20; i++){ new MailSender() .title("Email from FantJ to you.")
                    .content("Hee hee")
                    .contentType(MailContentTypeEnum.TEXT)
                    .targets(new ArrayList<String>(){{
                        add("[email protected]");
                    }})
                    .send();
            System.out.println("The first"+i+"This time sent successfully!"); }}}Copy the code

The third method is an interface I wrote to send emails. Can refer to my article Java send QQ mail

###### I introduce three (four) attributes of the @Scheduled annotations:

  • Cron: If you know something about Linux, you can search it for yourself. It’s not hard.

  • FixedRate and fixedDelay: This is very similar to the two methods of Timer (rate and delay). If I have to be rude, the first one is to start the Timer when the task starts running, and the second one is to start the Timer when the task finishes.

  • InitialDelay: This property sets the first execution delay. It needs to work with fixedDelay, fixedRate, and Crom.

### New problem thinking

This approach is improving all the time, but imagine a situation where a server that is performing a scheduled task fails and how many times it has been executed before. If we persisted the scheduled tasks to the database and maintained them as if they were normal logical data, we could avoid the various special cases encountered in the project.

Spingboot2 integrates the Quartz framework to persist scheduled tasks

It’s a hassle to declare in advance, because we need to join the IOC management and create the data table that Quartz asked us to create. And then just like playing Quartz (see above: Quartz Timed Task Framework standalone app), you play Quartz.

1. Import dependencies
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
        </dependency>
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz-jobs</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>

Copy the code

Hint, this project is based on springboot2 integration mybatic project: https://www.jianshu.com/p/c15094bd1965

2. Quartz infuses the Spring IOC configuration

QuartzConfiguration.java

package com.fantj.quartz; /** * Created by fant.j. */ @configuration @enablesCheduling public class QuartzConfiguration {/** * Inheritance org. Springframework. Scheduling. Quartz. SpringBeanJobFactory * way of realizing the task instance * / public static class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements ApplicationContextAware { private transient AutowireCapableBeanFactory beanFactory; @Override public voidsetApplicationContext(final ApplicationContext context) { beanFactory = context.getAutowireCapableBeanFactory(); } /** * We can directly use spring injection in the job instance implementation class to call the spring IOC-managed instance * @param bundle * @return* @throws Exception */ @Override protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception { final Object job = super.createJobInstance(bundle); /** * Deliver the job instance to Spring IOC */ beanfactory.autoWirebean (job);returnjob; }} /** * Configure the task factory instance * @param applicationContext Spring context instance * @return*/ @bean public JobFactory JobFactory (ApplicationContext ApplicationContext) {/** * Use custom task factory to integrate spring instances to complete the build task * see {@link AutowiringSpringBeanJobFactory} */ AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory(); jobFactory.setApplicationContext(applicationContext);returnjobFactory; } /** * configure the task scheduler * use the project dataSource as the quartz dataSource * @param jobFactory custom configure the task factory * @param dataSource dataSource instance * @return
     * @throws Exception
     */
    @Bean(destroyMethod = "destroy",autowire = Autowire.NO) public SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory, DataSource dataSource) throws Exception { SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean(); / / to the scheduler will spring management job custom factory maintenance schedulerFactoryBean. SetJobFactory (jobFactory); / / set cover existing task schedulerFactoryBean setOverwriteExistingJobs (true); / / after completion of project startup, wait for 2 seconds after the start executing the scheduler initialization schedulerFactoryBean. SetStartupDelay (2); / / set the scheduler to run automatically schedulerFactoryBean. SetAutoStartup (true); / / set up the data source, the use and project data source schedulerFactoryBean. SetDataSource (dataSource); / / set the context spring bean name schedulerFactoryBean. SetApplicationContextSchedulerContextKey ("applicationContext"); / / set the configuration file location schedulerFactoryBean. SetConfigLocation (new ClassPathResource ("/quartz.properties"));
        returnschedulerFactoryBean; }}Copy the code

Look at the second to last line of code, need a configuration file, so…

Quartz. The properties configuration
The scheduler instance name
org.quartz.scheduler.instanceName = quartzScheduler

The scheduler instance number is automatically generated
org.quartz.scheduler.instanceId = AUTO

Persistent configuration
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX

MySQL database
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate

# Quartz table prefix name
org.quartz.jobStore.tablePrefix = QRTZ_

Enable distributed deployment
org.quartz.jobStore.isClustered = true
# Configure whether to use
org.quartz.jobStore.useProperties = false

# Distributed node validity check interval, in milliseconds
org.quartz.jobStore.clusterCheckinInterval = 20000

Thread pool implementation class
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool

# Maximum number of concurrent threads to execute
org.quartz.threadPool.threadCount = 10

# Thread priority
org.quartz.threadPool.threadPriority = 5

The task will not be executed after being configured as a daemon thread
#org.quartz.threadPool.makeThreadsDaemons=true

Configure whether to enable automatic loading of scheduled tasks in the database. Default is true
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true

Copy the code

###### Create a table it may surprise you, but it requires eleven tables to support it.

#  
# In your Quartz properties file, you'll need to set   
# org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate  
#  
#  
# By: Ron Cordell - roncordell  
# I didn't see this anywhere, so I thought I'd post it here. This is the script from Quartz to create the tables in a MySQL database, modified to use INNODB instead of MYISAM.
  
DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;  
DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;  
DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;  
DROP TABLE IF EXISTS QRTZ_LOCKS;  
DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;  
DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;  
DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;  
DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;  
DROP TABLE IF EXISTS QRTZ_TRIGGERS;  
DROP TABLE IF EXISTS QRTZ_JOB_DETAILS;  
DROP TABLE IF EXISTS QRTZ_CALENDARS;  
  
CREATE TABLE QRTZ_JOB_DETAILS(  
SCHED_NAME VARCHAR(120) NOT NULL,  
JOB_NAME VARCHAR(200) NOT NULL,  
JOB_GROUP VARCHAR(200) NOT NULL,  
DESCRIPTION VARCHAR(250) NULL,  
JOB_CLASS_NAME VARCHAR(250) NOT NULL,  
IS_DURABLE VARCHAR(1) NOT NULL,  
IS_NONCONCURRENT VARCHAR(1) NOT NULL,  
IS_UPDATE_DATA VARCHAR(1) NOT NULL,  
REQUESTS_RECOVERY VARCHAR(1) NOT NULL,  
JOB_DATA BLOB NULL,  
PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP))  
ENGINE=InnoDB;  
  
CREATE TABLE QRTZ_TRIGGERS (  
SCHED_NAME VARCHAR(120) NOT NULL,  
TRIGGER_NAME VARCHAR(200) NOT NULL,  
TRIGGER_GROUP VARCHAR(200) NOT NULL,  
JOB_NAME VARCHAR(200) NOT NULL,  
JOB_GROUP VARCHAR(200) NOT NULL,  
DESCRIPTION VARCHAR(250) NULL,  
NEXT_FIRE_TIME BIGINT(13) NULL,  
PREV_FIRE_TIME BIGINT(13) NULL,  
PRIORITY INTEGER NULL,  
TRIGGER_STATE VARCHAR(16) NOT NULL,  
TRIGGER_TYPE VARCHAR(8) NOT NULL,  
START_TIME BIGINT(13) NOT NULL,  
END_TIME BIGINT(13) NULL,  
CALENDAR_NAME VARCHAR(200) NULL,  
MISFIRE_INSTR SMALLINT(2) NULL,  
JOB_DATA BLOB NULL,  
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),  
FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)  
REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP))  
ENGINE=InnoDB;  
  
CREATE TABLE QRTZ_SIMPLE_TRIGGERS (  
SCHED_NAME VARCHAR(120) NOT NULL,  
TRIGGER_NAME VARCHAR(200) NOT NULL,  
TRIGGER_GROUP VARCHAR(200) NOT NULL,  
REPEAT_COUNT BIGINT(7) NOT NULL,  
REPEAT_INTERVAL BIGINT(12) NOT NULL,  
TIMES_TRIGGERED BIGINT(10) NOT NULL,  
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),  
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)  
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))  
ENGINE=InnoDB;  
  
CREATE TABLE QRTZ_CRON_TRIGGERS (  
SCHED_NAME VARCHAR(120) NOT NULL,  
TRIGGER_NAME VARCHAR(200) NOT NULL,  
TRIGGER_GROUP VARCHAR(200) NOT NULL,  
CRON_EXPRESSION VARCHAR(120) NOT NULL,  
TIME_ZONE_ID VARCHAR(80),  
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),  
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)  
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))  
ENGINE=InnoDB;  
  
CREATE TABLE QRTZ_SIMPROP_TRIGGERS  
  (            
    SCHED_NAME VARCHAR(120) NOT NULL,  
    TRIGGER_NAME VARCHAR(200) NOT NULL,  
    TRIGGER_GROUP VARCHAR(200) NOT NULL,  
    STR_PROP_1 VARCHAR(512) NULL,  
    STR_PROP_2 VARCHAR(512) NULL,  
    STR_PROP_3 VARCHAR(512) NULL,  
    INT_PROP_1 INT NULL,  
    INT_PROP_2 INT NULL,  
    LONG_PROP_1 BIGINT NULL,  
    LONG_PROP_2 BIGINT NULL,  
    DEC_PROP_1 NUMERIC(13,4) NULL,  
    DEC_PROP_2 NUMERIC(13,4) NULL,  
    BOOL_PROP_1 VARCHAR(1) NULL,  
    BOOL_PROP_2 VARCHAR(1) NULL,  
    PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),  
    FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)   
    REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))  
ENGINE=InnoDB;  
  
CREATE TABLE QRTZ_BLOB_TRIGGERS (  
SCHED_NAME VARCHAR(120) NOT NULL,  
TRIGGER_NAME VARCHAR(200) NOT NULL,  
TRIGGER_GROUP VARCHAR(200) NOT NULL,  
BLOB_DATA BLOB NULL,  
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),  
INDEX (SCHED_NAME,TRIGGER_NAME, TRIGGER_GROUP),  
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)  
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))  
ENGINE=InnoDB;  
  
CREATE TABLE QRTZ_CALENDARS (  
SCHED_NAME VARCHAR(120) NOT NULL,  
CALENDAR_NAME VARCHAR(200) NOT NULL,  
CALENDAR BLOB NOT NULL,  
PRIMARY KEY (SCHED_NAME,CALENDAR_NAME))  
ENGINE=InnoDB;  
  
CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS (  
SCHED_NAME VARCHAR(120) NOT NULL,  
TRIGGER_GROUP VARCHAR(200) NOT NULL,  
PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP))  
ENGINE=InnoDB;  
  
CREATE TABLE QRTZ_FIRED_TRIGGERS (  
SCHED_NAME VARCHAR(120) NOT NULL,  
ENTRY_ID VARCHAR(95) NOT NULL,  
TRIGGER_NAME VARCHAR(200) NOT NULL,  
TRIGGER_GROUP VARCHAR(200) NOT NULL,  
INSTANCE_NAME VARCHAR(200) NOT NULL,  
FIRED_TIME BIGINT(13) NOT NULL,  
SCHED_TIME BIGINT(13) NOT NULL,  
PRIORITY INTEGER NOT NULL,  
STATE VARCHAR(16) NOT NULL,  
JOB_NAME VARCHAR(200) NULL,  
JOB_GROUP VARCHAR(200) NULL,  
IS_NONCONCURRENT VARCHAR(1) NULL,  
REQUESTS_RECOVERY VARCHAR(1) NULL,  
PRIMARY KEY (SCHED_NAME,ENTRY_ID))  
ENGINE=InnoDB;  
  
CREATE TABLE QRTZ_SCHEDULER_STATE (  
SCHED_NAME VARCHAR(120) NOT NULL,  
INSTANCE_NAME VARCHAR(200) NOT NULL,  
LAST_CHECKIN_TIME BIGINT(13) NOT NULL,  
CHECKIN_INTERVAL BIGINT(13) NOT NULL,  
PRIMARY KEY (SCHED_NAME,INSTANCE_NAME))  
ENGINE=InnoDB;  
  
CREATE TABLE QRTZ_LOCKS (  
SCHED_NAME VARCHAR(120) NOT NULL,  
LOCK_NAME VARCHAR(40) NOT NULL,  
PRIMARY KEY (SCHED_NAME,LOCK_NAME))  
ENGINE=InnoDB;  
  
CREATE INDEX IDX_QRTZ_J_REQ_RECOVERY ON QRTZ_JOB_DETAILS(SCHED_NAME,REQUESTS_RECOVERY);  
CREATE INDEX IDX_QRTZ_J_GRP ON QRTZ_JOB_DETAILS(SCHED_NAME,JOB_GROUP);  
  
CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);  
CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP);  
CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME);  
CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);  
CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE);  
CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);  
CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);  
CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME);  
CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);  
CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);  
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);  
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);  
  
CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME);  
CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);  
CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);  
CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP);  
CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);  
CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);  
  
commit;   
Copy the code

##### Ok, start writing the scheduled task business

First we need to define a subclass of Job to write Job detail

package com.fantj.quartz.notSpringFrame; /** * public implements Job {public implements JobMyJob(){} @override Public void execute(JobExecutionContext arg0) throws JobExecutionException {DateFormat df=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
        System.out.println("Test Quartz"+ df.format(Calendar.getInstance().getTime())); }}Copy the code

Second, I demonstrate how to inject and use scheduled tasks in ServiceImpl.

package com.fantj.service.impl; /** * Created by Fant.J. */ @Service public class UserServiceImpl implements UserService { @Autowired private UserMapper  userMapper; @autoWired Private Scheduler Scheduler; // Testing timed Tasks of the Quartz framework Public void sendMail() throws Exception {// Set the start time to 1 minute later long startAtTime = System.currentTimeMillis() + 1000 * 60; // Task name String name = uuid.randomuuid ().toString(); String group = myjob.class.getName (); // Task group String group = myjob.class.getName (); JobDetail JobDetail = jobBuilder.newJob (myjob.class).withidentity (name,group).build(); / / create a task Trigger Trigger the Trigger. = TriggerBuilder newTrigger () withIdentity (name, group). StartAt (new Date (startAtTime)). The build ();  Scheduler. scheduleJob(jobDetail, trigger); }}Copy the code

Again, like quartz on a single player, you pass in two objects (a JobDetail and a Trigger), task details and triggers. Do not understand the above has made a detailed introduction. Ok, now we start the project, you can see the console print, and the database quar_ tables also automatically fill in the scheduled task information.

We have probably just completed the persistence of Quartz. As we mentioned above, the main point of Quartz is the controllability of scheduled tasks, so if you need to add, delete, change and check the scheduled tasks on the admin page. I recommend a blog, write well, http://blog.csdn.net/u012907049/article/details/73801122

And thank you to the author.

Finally, thank you. This is a long article.