天天看点

快速上手Quartz定时任务框架Java实现定时任务的方式Quartz任务调度框架CronExpression表达式

Java实现定时任务的方式

一、线程等待(不建议使用,任务复杂时存在内存泄露风险)

Thread myThread = new Thread(new Runnable() {
    @Override
    public void run() {
        while (true) {
            System.out.println("TestThreadWait is called!");
            try {
                // 使用线程休眠来实现周期执行
                Thread.sleep(1000 * 3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
});
myThread.start();
           

二、Timer

package com.changan.test;

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

public class Main {
    public static void main(String[] args) {
        /*Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("执行定时任务");
            }
        },1000,1000);*/

        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                System.out.println("TimerTask is called!");
            }
        };

        Timer timer = new Timer();
        /*
         * schedule 和 scheduleAtFixedRate 区别:
         *  可将schedule理解为scheduleAtFixedDelay,
         *  两者主要区别在于delay和rate
         *  1、schedule,如果第一次执行被延时(delay),
         *      随后的任务执行时间将以上一次任务实际执行完成的时间为准
         *  2、scheduleAtFixedRate,如果第一次执行被延时(delay),
         *      随后的任务执行时间将以上一次任务开始执行的时间为准(需考虑同步)
         *
         *  参数:1、任务体    2、延时时间(可以指定执行日期)3、任务执行间隔时间
         */
        // timer.schedule(task, 0, 1000 * 3);
        timer.scheduleAtFixedRate(task, 0, 1000 * 3);
    }
}
           

三、ScheduledExecutorService

package com.changan.test;

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class Main {
    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            public void run() {
                System.out.println("ScheduledExecutorService Task is called!");
            }
        };
        ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
        // 参数:1、任务体 2、首次执行的延时时间
        //      3、任务执行间隔 4、间隔时间单位
        service.scheduleAtFixedRate(runnable, 0, 3, TimeUnit.SECONDS);
    }
}
           

四、@Schedule

1、配置

在spring boot的启动类上加@EnableScheduling注解,允许支持@Scheduled:

@SpringBootApplication
@EnableScheduling
public class Quartz01Application {

    public static void main(String[] args) {
        SpringApplication.run(Quartz01Application.class, args);
    }
}
           

2、任务类

@Component
public class ScheduleTask {

    // 每隔5秒执行一次
    @Scheduled(cron = "0/5 * * * * ?")
    public void printSay() {
        System.out.println("每隔5秒执行一次:" + new Date());
    }
}
           

Quartz任务调度框架

一、Quartz介绍

quartz是一种基于java实现的任务调度框架,可以定时自动的执行你想要执行的任何任务。

quartz官网:http://www.quartz-scheduler.org/

二、Quartz的组成

任务Job(你要做什么事? 将要执行的操作)

job就是你想要实现的任务类,每一个job必须实现org.quartz.job接口。

触发器Trigger(你什么时候去做? cron表达式)

Trigger为你执行任务的触发器,比如你想每天定时3点发送一份统计邮件,Trigger将会设置3点进行执行该任务。

调度器Scheduler(你什么时候需要做什么事?)

Scheduler为任务的调度器,它会将任务job及触发器Trigger整合起来,负责基于Trigger设定的时间来执行Job。

二、使用Java实现Quartz

搭建 quartzmaven 项目

快速上手Quartz定时任务框架Java实现定时任务的方式Quartz任务调度框架CronExpression表达式

项目名为 quartzmaven

快速上手Quartz定时任务框架Java实现定时任务的方式Quartz任务调度框架CronExpression表达式

添加依赖

<dependencies>
    <!--核心包-->
    <dependency>
        <groupId>org.quartz-scheduler</groupId>
        <artifactId>quartz</artifactId>
        <version>2.3.2</version>
    </dependency>
    <!--工具-->
    <dependency>
        <groupId>org.quartz-scheduler</groupId>
        <artifactId>quartz-jobs</artifactId>
        <version>2.3.2</version>
    </dependency>
</dependencies>
           

定义 PrintTimeJob 任务类 进行打印当前时间操作

package com.cp.job;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author : CP
 * @version: 1.0
 * @program : quartzmaven
 * @description : 打印时间
 * @date : 2021-03-20 10:11
 **/
public class PrintTimeJob implements Job {
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        //获取当前系统时间
        Date date = new Date();
        //定义时间格式
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //将获取的系统时间根据定义的时间格式进行格式化
        String format = simpleDateFormat.format(date);
        //根据定义的时间格式打印获取的时间
        System.out.println("执行定时任务,当前时间为:"+format);
    }
}
           

创建 PrintTimeSchedulerDemo 类 进行 打印时间表计划演示

package com.cp.test;

import com.cp.job.PrintTimeJob;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

/**
 * @author : CP
 * @version: 1.0
 * @program : quartzmaven
 * @description : 调用打印时间
 * @date : 2021-03-20 10:18
 **/
public class PrintTimeSchedulerDemo {
    public static void main(String[] args) throws SchedulerException {
        //1、调度器(Schedular),从工厂中获取调度实例(默认:实例化new StdSchedulerFactory();)
        Scheduler scheduler= StdSchedulerFactory.getDefaultScheduler();
        //2、任务实例(JobDetail)
        //加载任务类,与HelloJob完成绑定,要求HelloJob实现Job接口
        JobDetail jobDetail= JobBuilder.newJob(PrintTimeJob.class)
                //参数1:任务的名称(唯一实例);参数2:任务组的名称
                .withIdentity("job1","group1")
                .build();
        //3、触发器(Trigger)
        Trigger trigger= TriggerBuilder.newTrigger()
                //参数1:触发器的名称(唯一实例);参数2:触发器组的名称
                .withIdentity("trigger1","group1")
                //马上启动触发器
                .startNow()
                //每5秒执行一次
                .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(5))
                .build();
        //让调度器关联任务和触发器,保证按照触发器定义的条件执行任务
        scheduler.scheduleJob(jobDetail,trigger);
        //启动
        scheduler.start();
    }
}

           

运行结果如下图:

快速上手Quartz定时任务框架Java实现定时任务的方式Quartz任务调度框架CronExpression表达式

三、使用Springboot整合Quartz定时任务框架

快速上手Quartz定时任务框架Java实现定时任务的方式Quartz任务调度框架CronExpression表达式

项目名为 quartz-boot

快速上手Quartz定时任务框架Java实现定时任务的方式Quartz任务调度框架CronExpression表达式

不勾选依赖

快速上手Quartz定时任务框架Java实现定时任务的方式Quartz任务调度框架CronExpression表达式

添加依赖

<!-- Quartz -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
           

在主启动类添加 @EnableScheduling 注解

package com.cp;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableScheduling	//添加注解
public class QuartzBootApplication {

    public static void main(String[] args) {
        SpringApplication.run(QuartzBootApplication.class, args);
    }

}

           

定义 QuartzJob任务类 进行打印当前时间操作

package com.cp.job;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author : CP
 * @version: 1.0
 * @program : quartz-boot
 * @description :
 * @date : 2021-03-20 10:34
 **/
public class QuartzJob implements Job {
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        //获取当前系统时间
        Date date = new Date();
        //定义时间格式
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //将获取的系统时间根据定义的时间格式进行格式化
        String format = simpleDateFormat.format(date);
        //根据定义的时间格式打印获取的时间
        System.out.println("执行定时任务,当前时间为:"+format);
    }
}

           

创建 QuartzConfig 类 调度器

package com.cp.config;

import com.cp.job.QuartzJob;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.scheduling.quartz.SimpleTriggerFactoryBean;

/**
 * Quartz配置类
 */
@Configuration
public class QuartzConfig {
    /**
     * 1、创建Job对象
     */
    @Bean
    public JobDetailFactoryBean jobDetailFactoryBean(){
        JobDetailFactoryBean factoryBean=new JobDetailFactoryBean();
        //关联我们自己的Job类
        factoryBean.setJobClass(QuartzJob.class);
        return factoryBean;
    }

    /**
     * 2、创建Trigger对象
     */
    @Bean
    public SimpleTriggerFactoryBean simpleTriggerFactoryBean(JobDetailFactoryBean jobDetailFactoryBean){
        SimpleTriggerFactoryBean factoryBean=new SimpleTriggerFactoryBean();
        //关联JobDetail对象
        factoryBean.setJobDetail(jobDetailFactoryBean.getObject());
        //该参数表示一个执行的毫秒数
        factoryBean.setRepeatInterval(2000); //每隔2秒执行一次
        //重复次数
        factoryBean.setRepeatCount(5);
        return factoryBean;
    }

    /**
     * 3、创建Scheduler
     */
    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(SimpleTriggerFactoryBean simpleTriggerFactoryBean){
        SchedulerFactoryBean factoryBean=new SchedulerFactoryBean();
        //关联trigger
        factoryBean.setTriggers(simpleTriggerFactoryBean.getObject());
        return factoryBean;
    }
}

           

运行结果如下:

快速上手Quartz定时任务框架Java实现定时任务的方式Quartz任务调度框架CronExpression表达式

四、使用Springboot+mybatis整合Quartz定时任务框架实现定时向数据库插入一条数据

在quartz-boot项目上的基础添加依赖

<!--lombok-->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

<!-- mybatis-plus -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.1</version>
</dependency>

<!--java连接mysql-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.13</version>
</dependency>

<!--velocity模板引擎-->
<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-engine-core</artifactId>
    <version>2.2</version>
</dependency>

<!--mybatis-plus自动代码生成-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.4.1</version>
</dependency>

<!--swagger-->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
</dependency>

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
</dependency>
           

创建 CodeGenerator 类 开始搭建框架

package com.cp;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import org.apache.commons.lang3.StringUtils;

import java.util.Scanner;

/**
 * @author : CP
 * @version: 1.0
 * @program : xinguan-parent
 * @description : 框架构造
 * @date : 2020-11-30 21:19
 **/
public class CodeGenerator {

    /**
     * <p>
     * 读取控制台内容
     * </p>
     */
    public static String scanner(String tip) {
        Scanner scanner = new Scanner(System.in);
        StringBuilder help = new StringBuilder();
        help.append("请输入" + tip + ":");
        System.out.println(help.toString());
        if (scanner.hasNext()) {
            String ipt = scanner.next();
            if (StringUtils.isNotEmpty(ipt)) {
                return ipt;
            }
        }
        throw new MybatisPlusException("请输入正确的" + tip + "!");
    }

    public static void main(String[] args) {
        // 创建代码生成器对象
        AutoGenerator mpg = new AutoGenerator();

        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        gc.setOutputDir(scanner("请输入你的项目路径") + "/src/main/java");
        gc.setAuthor("cp");
        //生成之后是否打开资源管理器
        gc.setOpen(false);
        //重新生成时是否覆盖文件
        gc.setFileOverride(false);
        //%s 为占位符
        //mp生成service层代码,默认接口名称第一个字母是有I
        gc.setServiceName("%sService");
        //设置主键生成策略  自动增长
        gc.setIdType(IdType.AUTO);
        //设置Date的类型   只使用 java.util.date 代替
        gc.setDateType(DateType.ONLY_DATE);
        //开启实体属性 Swagger2 注解
        gc.setSwagger2(true);
        mpg.setGlobalConfig(gc);

        // 数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8");
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("root");
        //使用mysql数据库
        dsc.setDbType(DbType.MYSQL);
        mpg.setDataSource(dsc);

        // 包配置
        PackageConfig pc = new PackageConfig();
        pc.setModuleName(scanner("请输入模块名"));
        pc.setParent("com.cp");
        pc.setController("controller");
        pc.setService("service");
        pc.setServiceImpl("service.impl");
        pc.setMapper("mapper");
        pc.setEntity("entity");
        pc.setXml("mapper");
        mpg.setPackageInfo(pc);

        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        //设置哪些表需要自动生成
        strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));

        //实体类名称驼峰命名
        strategy.setNaming(NamingStrategy.underline_to_camel);

        //列名名称驼峰命名
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        //使用简化getter和setter
        strategy.setEntityLombokModel(true);
        //设置controller的api风格  使用RestController
        strategy.setRestControllerStyle(true);
        //驼峰转连字符
        strategy.setControllerMappingHyphenStyle(true);
        //去除前置,不需要可以不填写,可以用逗号添加多个
        strategy.setTablePrefix("biz_");
        mpg.setStrategy(strategy);
        mpg.execute();
    }
}

           
快速上手Quartz定时任务框架Java实现定时任务的方式Quartz任务调度框架CronExpression表达式

配置 apllication.yaml

spring:
  application:
    name: quartz-boot
  # 数据源配置
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/demo?userUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
    username: root
    password: root
  # 格式化时区
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8
    # jackson实体转json时 为NULL不参加序列化的汇总
    default-property-inclusion: non_null

# 配置端口号
server:
  port: 8081

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
  #逻辑删除
  global-config:
    db-config:
      logic-delete-field: deleted  # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
      logic-delete-value: 1 # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
  # 扫描 Mapper.xml
  mapper-locations: classpath*:/mapper/*.xml
  # 配置别名
  type-aliases-package: com.cp.api.entity




           

在主启动类添加 @MapperScan(“com.cp.api.mapper”) 注解

package com.cp;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@MapperScan("com.cp.api.mapper")
@EnableScheduling
public class QuartzBootApplication {

    public static void main(String[] args) {
        SpringApplication.run(QuartzBootApplication.class, args);
    }

}
           

添加配置类 MyadaptableJobFactory

package com.cp.config;

import org.springframework.scheduling.quartz.AdaptableJobFactory;

import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.stereotype.Component;

//将该类实例化,使得可以直接用
@Component("myadaptableJobFactory")
public class MyadaptableJobFactory extends AdaptableJobFactory {

    //AutowireCapableBeanFactory可以将一个对象添加到Spring IOC容器中,并且完成该对象注入
    @Autowired
    private AutowireCapableBeanFactory autowireCapableBeanFactory;

    //该方法将实例化的任务对象手动的添加到SpringIOC容器中并且完成对象的注入
    @Override
    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
        Object object = super.createJobInstance(bundle);
        //将object对象添加到Spring IOC容器中并完成注入
        this.autowireCapableBeanFactory.autowireBean(object);
        return object;
    }
}

           

修改 QuartzConfig 类

//注入myadaptableJobFactory类
@Autowired
private MyadaptableJobFactory myadaptableJobFactory;
//在 schedulerFactoryBean 方法后添加 
factoryBean.setJobFactory(myadaptableJobFactory);
           

完整代码

package com.cp.config;

import com.cp.job.QuartzJob;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.scheduling.quartz.SimpleTriggerFactoryBean;

/**
 * Quartz配置类
 */
@Configuration
public class QuartzConfig {

    @Autowired
    private MyadaptableJobFactory myadaptableJobFactory;

    /**
     * 1、创建Job对象
     */
    @Bean
    public JobDetailFactoryBean jobDetailFactoryBean(){
        JobDetailFactoryBean factoryBean=new JobDetailFactoryBean();
        //关联我们自己的Job类
        factoryBean.setJobClass(QuartzJob.class);
        return factoryBean;
    }

    /**
     * 2、创建Trigger对象
     */
    @Bean
    public SimpleTriggerFactoryBean simpleTriggerFactoryBean(JobDetailFactoryBean jobDetailFactoryBean){
        SimpleTriggerFactoryBean factoryBean=new SimpleTriggerFactoryBean();
        //关联JobDetail对象
        factoryBean.setJobDetail(jobDetailFactoryBean.getObject());
        //该参数表示一个执行的毫秒数
        factoryBean.setRepeatInterval(2000); //每隔2秒执行一次
        //重复次数
        factoryBean.setRepeatCount(5);
        return factoryBean;
    }

    /**
     * 3、创建Scheduler
     */
    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(SimpleTriggerFactoryBean simpleTriggerFactoryBean){
        SchedulerFactoryBean factoryBean=new SchedulerFactoryBean();
        //关联trigger
        factoryBean.setTriggers(simpleTriggerFactoryBean.getObject());
        factoryBean.setJobFactory(myadaptableJobFactory);
        return factoryBean;
    }
}

           

操作结果

快速上手Quartz定时任务框架Java实现定时任务的方式Quartz任务调度框架CronExpression表达式

CronExpression表达式

格式:

[秒] [分] [时] [每月的第几日] [月] [每周的第几日] [年]

字段名 必须的 允许值 允许的特殊字符
Seconds YES 0-59

,

-

*

/

Minutes YES 0-59

,

-

*

/

Hours YES 0-23

,

-

*

/

Day of month YES 1-31

,

-

*

?

/

L

W

Month YES 1-12 or JAN-DEC

,

-

*

/

Day of week YES 1-7 or SUN-SAT

,

-

*

?

/

L

#

Year NO empty, 1970-2099

,

-

*

/

注意:有效范围为1-7的整数或SUN-SAT两个范围。1表示星期天,2表示星期一, 依次类推

特殊字符说明:

字符 含义

*

用于

指定字段中的所有值

。比如:

*

在分钟中表示

每一分钟

?

用于

指定日期中的某一天

,或是

星期中的某一个星期

-

用于

指定范围

。比如:

10-12

在小时中表示

10 点,11 点,12 点

,

用于

指定额外的值

。比如:

MON,WED,FRI

在日期中表示

星期一, 星期三, 星期五

/

用于

指定增量

。比如:

0/15

在秒中表示

0 秒, 15 秒, 30 秒, 45 秒

5/15

在秒中表示

5 秒,20 秒,35 秒,50 秒

L

在两个字段中拥有不同的含义。比如:

L

在日期(Day of month)表示

某月的最后一天

。在星期(Day of week)只表示

7

SAT

。但是,

值L

在星期(Day of week)中表示

某月的最后一个星期几

。比如:

6L

表示

某月的最后一个星期五

。也可以在日期(Day of month)中指定一个偏移量(从该月的最后一天开始).比如:

L-3

表示

某月的倒数第三天

W

用于指定工作日(星期一到星期五)比如:

15W

在日期中表示

到 15 号的最近一个工作日

。如果第十五号是周六, 那么触发器的触发在

第十四号星期五

。如果第十五号是星期日,触发器的触发在

第十六号周一

。如果第十五是星期二,那么它就会工作开始在

第十五号周二

。然而,如果指定

1W

并且第一号是星期六,那么触发器的触发在第三号周一,因为它不会 “jump” 过一个月的日子的边界。

L

W

可以在日期(day-of-month)合使用,表示

月份的最后一个工作日

#

用于

指定月份中的第几天

。比如:

6#3

表示

月份的第三个星期五

(day 6 = Friday and “#3” = the 3rd one in the month)。其它的有,``2#1

表示

月份第一个星期一

4#5

表示

月份第五个星期三

。注意: 如果只是指定

#5

,则触发器在月份中**不会**触发。

注意:字符不区分大小写,

MON

mon

相同。

cronExpression 示例

表达式 含义

0 0 12 * * ?

每天中午 12 点

0 15 10 ? * *

每天上午 10 点 15 分

0 15 10 * * ?

每天上午 10 点 15 分

0 15 10 * * ? *

每天上午 10 点 15 分

0 15 10 * * ? 2005

在 2005 年里的每天上午 10 点 15 分

0 * 14 * * ?

每天下午 2 点到下午 2 点 59 分的每一分钟

0 0/5 14 * * ?

每天下午 2 点到 2 点 55 分每隔 5 分钟

0 0/5 14,18 * * ?

每天下午 2 点到 2 点 55 分, 下午 6 点到 6 点 55 分, 每隔 5 分钟

0 0-5 14 * * ?

每天下午 2 点到 2 点 5 分的每一分钟

0 10,44 14 ? 3 WED

3 月每周三的下午 2 点 10 分和下午 2 点 44 分

0 15 10 ? * MON-FRI

每周一到周五的上午 10 点 15 分

0 15 10 15 * ?

每月 15 号的上午 10 点 15 分

0 15 10 L * ?

每月最后一天的上午 10 点 15 分

0 15 10 L-2 * ?

每月最后两天的上午10点15分

0 15 10 ? * 6L

每月的最后一个星期五的上午 10 点 15 分

0 15 10 ? * 6L 2002-2005

2002 年到 2005 年每个月的最后一个星期五的上午 10 点 15 分

0 15 10 ? * 6#3

每月的第三个星期五的上午 10 点 15 分

0 0 12 1/5 * ?

每月的 1 号开始每隔 5 天的中午 12 点

0 11 11 11 11 ?

每年 11 月 11 号上午 11 点 11 分

| 3 月每周三的下午 2 点 10 分和下午 2 点 44 分 |

|

0 15 10 ? * MON-FRI

| 每周一到周五的上午 10 点 15 分 |

|

0 15 10 15 * ?

| 每月 15 号的上午 10 点 15 分 |

|

0 15 10 L * ?

| 每月最后一天的上午 10 点 15 分 |

|

0 15 10 L-2 * ?

| 每月最后两天的上午10点15分 |

|

0 15 10 ? * 6L

| 每月的最后一个星期五的上午 10 点 15 分 |

|

0 15 10 ? * 6L 2002-2005

| 2002 年到 2005 年每个月的最后一个星期五的上午 10 点 15 分 |

|

0 15 10 ? * 6#3

| 每月的第三个星期五的上午 10 点 15 分 |

|

0 0 12 1/5 * ?

| 每月的 1 号开始每隔 5 天的中午 12 点 |

|

0 11 11 11 11 ?

| 每年 11 月 11 号上午 11 点 11 分 |

快速上手Quartz定时任务框架Java实现定时任务的方式Quartz任务调度框架CronExpression表达式