详细介绍Quartz以及它和timer的区别,spring集成Quartz,以及Cron常用表达式:每隔N秒钟、每隔N分钟、每隔N小时、在N点定时执行一次(每天执行一次)

1. 文章引言


系统中通常有些需要自动执行的任务,这些任务可能每隔一段时间就要执行一次,也可能需要在指定的时间点自动执行,这些任务的自动执行必须使用任务的自动调度。

JDK为简单的任务调度提供了Timer支持,如下代码所示:

public static void main(String[] args) {
    
    
  Timer timer = new Timer();
  final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  TimerTask timerTask =
      new TimerTask() {
    
    
        @Override
        public void run() {
    
    
          String format = simpleDateFormat.format(new Date());
          System.out.println("每隔5秒输出timer信息,输出时间:" + format);
        }
      };
  timer.schedule(timerTask, 0, 5000);
}

输出结果如下图所示:

在这里插入图片描述

但对于更复杂的调度,例如:需要在某的时刻调度任务时。Timer就显得力不从心了,因而出现了Quartz任务调度框架。

QuartzOpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EEJ2SE应用程序相结合也可以单独使用。

Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的日程序表——Jobs可以做成标准的Java组件或EJBs

总之,Quartz是一款开源且丰富特性的任务调度库,能够集成与任何的java应用下到独立应用,大到电子商业系统。Quartz就是基于java实现的任务调度框架,用于执行你想要执行的任何任务。

什么是任务调度?任务调度就是我们系统中创建了N个任务,每个任务都有指定的时间进行执行,而这种多任务的执行策略就是任务调度。

Quartz的作用就是让任务调度变得更加丰富,高效,安全,而且是基于 Java 实现的,这样子开发者只需要调用几个接口坐下简单的配置,即可实现上述需求。

2. 引入Quartz


Quartz的使用也非常简单,我们需要在pom.xml中引入Quartzjar包:

如果你是spring boot项目,直接引入如下jar包:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-quartz</artifactId>
  <version>3.0.4</version>
</dependency>

如果你是spring mvc项目,则引入如下jar包:

<!--quartz-->
<dependency>
  <groupId>org.quartz-scheduler</groupId>
  <artifactId>quartz</artifactId>
  <version>2.3.2</version>
</dependency>

3. Cron表达式

3.1 简述Cron表达式


Cron表达式是用来配置CronTrigger实例,它是一个由 7个子表达式组成的字符串,每个字符都表示不同的日程细节:

在这里插入图片描述

  1. Seconds:秒

  2. Minutes:分钟

  3. Hours:小时

  4. Day-of-Month:月中的哪几天

  5. Month:月

  6. Day-of-Week:周中的哪几天

  7. Year:年

字 段 是 否 必 填 允 许 值 可 用 特 殊 字 符 备 注
秒(Seconds) 0-59 , - * / 标准实现不支持此字段。
分(Minutes) 0-59 , - * /
小时(Hours) 0-23 , - * /
月中的哪几天(Day of month) 1-31 , - * / ? L W C ?LW只有部分软件实现了
月(Month) 1-12 或 JAN-DEC , - * /
周中的哪几天(Day of week) 1-7 或 SUN-SAT , - * / ? L C # ?L#只有部分软件实现了Linux和Spring的允许值为0-7,07为周日Quartz的允许值为1-7,1为周日
年(Year) 不填写 或 1970-2099 , - * /

【注意】如下为特殊符号的说明:

特  殊  符  号 含  义
* 可用在所有字段中,表示对应时间域的每一个时刻,例如,***** 在分钟字段时,表示“每分钟”
? 该字符只在日期和星期字段中使用,它通常指定为“无意义的值”,相当于点位符
- 表达一个范围,如在小时字段中使用“10-12”,则表示从10到12点,即10,11,12
, 表达一个列表值,如在星期字段中使用“MON,WED,FRI”,则表示星期一,星期三和星期五
/ x/y表达一个等步长序列,x为起始值,y为增量步长值。如在分钟字段中使用0/15,则表示为0,15,30和45秒,而5/15在分钟字段中表示5,20,35,50,你也可以使用*/y,它等同于0/y
L 该字符只在日期和星期字段中使用,代表“Last”的意思,但它在两个字段中意思不同。L在日期字段中,表示这个月份的最后一天,如一月的31号,非闰年二月的28号;如果L用在星期中,则表示星期六,等同于7。但是,如果L出现在星期字段里,而且在前面有一个数值 X,则表示“这个月的最后X天”,例如,6L表示该月的最后星期五
W 该字符只能出现在日期字段里,是对前导日期的修饰,表示离该日期最近的工作日。例如15W表示离该月15号最近的工作日,如果该月15号是星期六,则匹配14号星期五;如果15日是星期日,则匹配16号星期一;如果15号是星期二,那结果就是15号星期二。但必须注意关联的匹配日期不能够跨月,如你指定1W,如果1号是星期六,结果匹配的是3号星期一,而非上个月最后的那天。W字符串只能指定单一日期,而不能指定日期范围
# 该字符只能在星期字段中使用,表示当月某个工作日。如6#3表示当月的第三个星期五(6表示星期五,#3表示当前的第三个),而4#5表示当月的第五个星期三,假设当月没有第五个星期三,忽略不触发

【注意】Cron表达式对特殊字符的大小写不敏感,对代表星期的缩写英文大小写也不敏感。

3.2 Cron常用表达式

常用表达式 说明
0 0 10,14,16 * * ? 每天上午10点,下午2点,4点
0 0/30 9-17 * * ? 朝九晚五工作时间内每半小时,从0分开始每隔30分钟发送一次
0 0 12 ? * WED 表示每个星期三中午12点
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期间的每1分钟触发
0 0/55 14 * * ? 在每天下午2点到下午2:55期间,从0开始到55分钟触发
0 0-5 14 * * ? 在每天下午2点到下午2:05期间的每1分钟触发
0 10,44 14 ? 3 WED 每年三月的星期三的下午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 ? * 6L 每月的最后一个星期五上午10:15触发
0 15 10 ? * 6L 2002-2005 2002年至2005年的每月的最后一个星期五上午10:15触发
0 15 10 ? * 6#3 每月的第三个星期五上午10:15触发

3.3 在线生成cron表达式

  1. https://cron.qqe2.com/

  2. http://cron.ciding.cc/

3.4 在线校验cron表达式

  1. https://tool.lu/crontab/

4. Quartz的使用


我们在使用Quartz时,一般是配合spring框架的。我们要在任务调度的方法上,添加@Configuration 、@EnableScheduling和@Scheduled注解。

  1. 每隔N秒钟执行一次

以每隔5秒钟执行一次为例子。

/**
* @author super先生
* @datetime 2023/4/8 15:23
* @desc
*/
@Configuration
@EnableScheduling
public class QuartzTest {
    
    

   /**
    * 每隔5秒钟执行一次
    *
    * @author super先生
    * @datetime 2023/4/8 15:59 
    */
   @Scheduled(cron = "0/5 * * * * ? ")
   public void testPerFSecond() {
    
    
       final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
       String format = simpleDateFormat.format(new Date());
       System.out.println("每隔5秒输出timer信息,输出时间:" + format);
   }
}

输出结果如下图:

在这里插入图片描述

  1. 每隔N分钟执行一次

以每隔1分钟执行一次为例子

/**
 * @author super先生
 * @datetime 2023/4/8 15:23
 * @desc
 */
@Configuration
@EnableScheduling
public class QuartzTest {
    
    

    /**
     * 每隔1分钟执行一次
     *
     * @author super先生
     * @datetime 2023/4/8 16:00
     */
    @Scheduled(cron = "0 0/1 * * * ? ")
    public void testPerOneMinute() {
    
    
        final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String format = simpleDateFormat.format(new Date());
        System.out.println("每隔1分钟输出timer信息,输出时间:" + format);
    }
}

输出结果如下图:

在这里插入图片描述

  1. 每隔N小时

以每隔1小时执行一次为例子

/**
 * @author super先生
 * @datetime 2023/4/8 15:23
 * @desc
 */
@Configuration
@EnableScheduling
public class QuartzTest {
    
    

    /**
     * 每隔1小时执行一次
     *
     * @author super先生
     * @datetime 2023/4/8 16:00
     */
    @Scheduled(cron = "0 0 0/1 * * ? ")
    public void testPerOneHour() {
    
    
        final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String format = simpleDateFormat.format(new Date());
        System.out.println("每隔1小时输出timer信息,输出时间:" + format);
    }
}

由于每隔1小时执行一次的时间较长,就没有打印结果,而是将corn表达式,粘贴到在线校验cron表达的网站中,输出结果如下图所示:

在这里插入图片描述

  1. 在N点定时执行一次

以在22点定时执行为例子,也就是每天22点执行一次

/**
* @author super先生
* @datetime 2023/4/8 15:23
* @desc
*/
@Configuration
@EnableScheduling
public class QuartzTest {
    
    
   /**
    * 以每天在21点55分定时执行为例子来演示每天执行一次
    *
    * @author super先生
    * @datetime 2023/4/8 16:00
    */
   @Scheduled(cron = "0 55 21 * * ? ")
   public void testPerDayOn22Clock() {
    
    
       final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
       String format = simpleDateFormat.format(new Date());
       System.out.println("每天定时21点55分输出timer信息,输出时间:" + format);
   }
}

输出结果如下图所示:

在这里插入图片描述

5. 文末总结


cron表达式有很多情形,比如每隔2分钟执行一次,定时在每天的13点执行一次等。

这都需要你在实际工作中,按照项目的需求来使用不同的cron表达式,以满足项目上的需要。

我曾在工作中就写过,在每天凌晨3点执行一次定时任务,来统计昨日的资金收入。

猜你喜欢

转载自blog.csdn.net/lvoelife/article/details/129748090