简介

在项目中我们经常会用到定时任务。本文介绍一些定时任务框架的区别。




QuartZ



xxl-job



SchedulerX 2.0



PowerJob



是否有前端页面











定时类型



CRON



CRON



CRON、固定频率、固定延迟、OpenAPI



CRON、固定频率、固定延迟、OpenAPI



支持的数据库



关系型数据库

(MySQL、Oracle...)



MySQL



人民币(不开源)



任意 Spring Data Jpa支持的关系型数据库(MySQL、Oracle...)



报警监控





邮件



短信



邮件,提供接口允许开发者扩展



任务类型



内置Java



内置Java、GLUE Java、Shell、Python等脚本



内置Java、外置Java(FatJar)、Shell、Python等脚本



内置Java、外置Java(容器)、Shell、Python等脚本



分布式任务





静态分片



MapReduce 动态分片



MapReduce 动态分片



在线任务治理



不支持



支持



支持



支持



日志白屏化



不支持



支持



不支持



支持



调度方式及性能



基于数据库锁,有性能瓶颈



基于数据库锁,有性能瓶颈



不详



无锁化设计,性能强劲无上限



DAG 工作流



不支持



不支持



支持



支持


        Timer、定时线程池、Spring的定时器,这三个就不写上了。这三者都没有前端页面,且不支持分布式(部署多个实例时只在一个实例上边指定定时任务)。

CRON

参考网址:​​quartz/Cron/Crontab表达式在线校验工具-BeJSON.com​

在线工具

​https://www.mawho.com/tool/cron.html​

​JSON在线编辑器-奇Q工具网​

简介

Cron表达式是一个字符串,字符串以5或6个空格隔开,分为6或7个域,每个域代表一个含义,Cron有如下两种格式:

  1. Seconds Minutes Hours DayofMonth Month DayofWeek Year
  2. Seconds Minutes Hours DayofMonth Month DayofWeek

Cron缺点

        只能在某一个域的值到达指定数字后才会运行任务,无法立刻运行。比如:想要从现在开始,每小时运行一次,是做不到的,对于这个需求,Cron只能做到按指定时间运行,例如0 0 * * * * ?:1:00:00, 2:00:00, 3:00:00 ...

(如果有哪位大佬有用Cron解决这个需求的方法请评论)

示例

每个元素可以是一个值(如:6), 一个连续区间(如:9-12), 一个间隔时间(如:8-18/4)(/4表示每隔4小时), 一个列表(如:1,3,5), 通配符。


含义



表达式



每隔5秒执行一次



*/5 * * * * ?



每隔1分钟执行一次



0 */1 * * * ?

或者0 * * * * *



每隔1小时执行一次



0 0 * * * * ?



每天23:00:00执行一次



0 0 23 * * ?



每个星期三中午12点



0 0 12 ? * WED



周一至周五的上午10:15触发



0 15 10 ? * MON-FRI



每月1号凌晨1:00:00执行一次



0 0 1 1 * ?



每月最后一天23:00:00执行一次



0 0 23 L * ?



每周星期天凌晨1:00:00实行一次



0 0 1 ? * L



在26分、29分、33分执行一次



0 26,29,33 * * * ?



2002-2006年的每个月的最后一个星期五上午10:15执行



0 15 10 ? 6L 2002-2006



朝九晚五工作时间内每半小时



0 0/30 9-17 * * ?



每月最后一日的上午10:15触发



0 15 10 L * ?



每月的最后一个星期五上午10:15触发



0 15 10 ? * 6L



每月的第三个星期五上午10:15触发



0 15 10 ? * 6#3


字段含义


字段



允许值



允许的特殊字符



秒(Seconds)



0~59的整数



, - * /    四个字符



分(Minutes)



0~59的整数



, - * /    四个字符



小时(Hours)



0~23的整数



, - * /    四个字符



日期(DayofMonth)



1~31的整数(需要考虑月的天数)



,- * ? / L W C     八个字符



月份(Month)



1~12的整数或者 JAN-DEC



, - * /    四个字符



星期(DayofWeek)



1~7的整数或者 SUN-SAT (1=SUN)



, - * ? / L C #     八个字符



年(Year)(可选)



1970~2099



, - * /    四个字符



符号



说明



*



表示匹配该域的任意值。假如在Minutes域使用*, 即表示每分钟都会触发事件。





只能用在DayofMonth和DayofWeek两个域。它也匹配域的任意值,但实际不会。因为DayofMonth和DayofWeek会相互影响。例如想在每月的20日触发调度,不管20日到底是星期几,则只能使用如下写法: 13 13 15 20 * ?, 其中最后一位只能用?,而不能使用*,如果使用*表示不管星期几都会触发,实际上并不是这样。



-



表示范围。例如在Minutes域使用5-20,表示从5分到20分钟每分钟触发一次



/



表示起始时间(/的左侧)与间隔时间(/的右侧)。开始触发,然后每隔固定时间触发一次。

例如:Minutes域中:“0/15”表示从0分开始,每15分钟一次。“3/20”表示从3分开始,每20分钟一次(与“3,23,43”等效)



,



表示列出枚举值。例如:在Minutes域使用5,20,则意味着在5分和20分都触发一次。



L



单词“last”的缩写。只能出现在DayofMonth和DayofWeek域。

L用于DayofMonth域:表示当月最后一天,L前加数字表示倒数第几天(如:3L:倒数第三天)

L用于DayofWeek域:表示最后一个周六,L加数字表示最后一个周值(如:3L:最后一个周二)
注意:在使用“L”参数时,不要指定列表或范围,因为这会导致问题



W



表示工作日(周一到周五),只能出现在DayofMonth域。指定离指定日的最近的一个平日。
例如:在 DayofMonth使用5W。

    如果5日是星期六,则将在最近的工作日:星期五,即4日触发。

    如果5日是星期天,则在6日(周一)触发;

    如果5日在星期一到星期五中的一天,则就在5日触发。
    另外一点,W的最近寻找不会跨过月份 。



LW



某个月最后一个工作日,即最后一个星期五。



#



每个月第几个星期几,只能出现在DayofWeek域。例如:4#2,表示某月的第二个星期三。



C



代表“Calendar”的意思。它的意思是计划所关联的日期,如果日期没有被关联,则相当于日历中所有日期。

例如5C在日期字段中就相当于日历5日以后的第一天。1C在星期字段中相当于星期日后的第一天。