使用 QWorker 做为计划任务引擎
QWorker 提供了 Plan 函数来提供计划任务功能的支持。每个任务做为一个作业,可以在指定的时间点被触发执行。而 cron 作为 Linux 操作系统下计划任务的标准被广大用户所熟知,QWorker 也就不再闭门造车,决定遵从这一规则。但是,可但是,通过百度后,你会发现有两个,一个是 crontab 标准,精确到分钟,另一个是 java 的 spring 框架使用的仿 cron 格式,精确到秒。在一翻无谓的挣扎和犹豫之后,最终决定使用 spring 兼容的实现,原来基于 cron 的实现被推倒重新实现。
好了,确定了目标并实现之后,我们就是实践了。计划任务作业的创建与普通的作业其实并没有什么不同,如果非要说有啥不同,那就是计划任务作业的接口函数名为 Plan,并且使用了一个 TQPlanMask 类型的参数来传递计划任务的调度计划。
先来看看 Plan 函数的声明:
|
1
2
3
4
5
6
7
8
|
function Plan(AProc: TQJobProc; const APlan: TQPlanMask; AData: Pointer;ARunInMainThread: Boolean = False;AFreeType: TQJobDataFreeType = jdfFreeByUser): IntPtr; overload;
function Plan(AProc: TQJobProc; const APlan: QStringW; AData: Pointer;ARunInMainThread: Boolean = False;AFreeType: TQJobDataFreeType = jdfFreeByUser): IntPtr; overload;
function Plan(AProc: TQJobProcG; const APlan: TQPlanMask; AData: Pointer;ARunInMainThread: Boolean = False;AFreeType: TQJobDataFreeType = jdfFreeByUser): IntPtr; overload;
function Plan(AProc: TQJobProcG; const APlan: QStringW; AData: Pointer;ARunInMainThread: Boolean = False;AFreeType: TQJobDataFreeType = jdfFreeByUser): IntPtr; overload;
{$IFDEF UNICODE}
function Plan(AProc: TQJobProcA; const APlan: TQPlanMask; AData: Pointer;ARunInMainThread: Boolean = False;AFreeType: TQJobDataFreeType = jdfFreeByUser): IntPtr; overload;
function Plan(AProc: TQJobProcA; const APlan: QStringW; AData: Pointer;ARunInMainThread: Boolean = False;AFreeType: TQJobDataFreeType = jdfFreeByUser): IntPtr; overload;
{$ENDIF}
|
好了,简单说下几个参数都干啥的,AProc、AData、ARunInMainThread、AFreeType 这四个参数与普通的作业并没有任何不同,依然是作业处理函数、附加数据指针、是否运行在主线程、附加数据指针的释放方式,唯一多出来的参数就是 APlan,从上面的声明可以看出来,我们提供了两个重载,一个是 TQPlanMask 类型,另外一个是直接的 QStringW,我们可以根据需要选择一个格式:
- TQPlanMask 格式可以提供更多额外的控制,比如计划任务的首次执行时间范围。
- 如果没有额外的控制需要,QStringW 格式是直接设置作业调度的掩码,明显更方便一些。
下面我们看调用的一个例子:
|
1
|
Workers.Plan(DoPlanJob, '0 * * * * * "每分钟重复一次的作业"', nil, True);
|
这样一句代码就定义了一个计划任务,要求在每分钟执行一次作业 DoPlanJob。为什么呢,我们就要从这个计划任务的格式掩码说起。
QWorker 的计划任务掩码参考自 Spring ,共有 6-7 部分组成,格式如下:
秒 分 时 日 月 周 [年]
其中,年是可选,没有的话,就忽略它的检查。第一个部分都有自己的取值范围和为了方便条件设定的通配符,年、月、日和时、分、秒我觉得就不用细说取值范围了,相信你也知道,只是特别说明以下几点:
- 小时使用的是 24 小时制,所以范围是0-23;
- 月可以使用月份的英文缩写,如 JAN、MAY 等;
- 周是以周一为起点,定义为 1 ,剩下的依次类推,也就是说周日为7,当然更清晰的是使用星期的英文缩写,如 SUN、WED 等;为了和 Linux 的 cron 保持兼容,会同时将 0 识别为周日。
- 年份的表示范围是 1970~9999,不过这个估计很少用了。
- 补充一点,月或周使用英文时不区分大小写,所以 JAN 和 jAn 的结果是一样一样的。
然后我们说一下通配符。所有的部分都支持 -、* 和 / 三种,日部分还额外支持 L、W 和 ?,周额外支持 L 和 ?。下面说一下各个通配符的含义:
- *
表示所有值. 例如:在分的字段上设置 “*”,表示每一分钟都会触发; - ?
表示不指定值。使用的场景为不需要关心当前设置这个字段的值。例如:要在每月的10号触发一个操作,但不关心是周几,所以需要周位置的那个字段设置为“?”,具体设置为 0 0 0 10 * ?; - –
表示区间。例如 在小时上设置“10-12”,表示 10、11、12 点都会触发; - ,
表示指定多个值,例如在周字段上设置 “MON,WED,FRI” 表示周一,周三和周五触发; - /
用于递增触发。如在秒上面设置 “5/15” 表示从 5 秒开始,每增 15 秒触发(5、20、35、50)。 在月字段上设置 “1/3” 所示每月 1 号开始,每隔三天触发一次; - L
表示最后的意思,取英文 Last 的缩写。在日字段设置上,表示当月的倒数第几天(依据当前月份,如果是二月还会依据是否是闰年),如 L-2 代表从月份的最后一天开始倒数两天,L0 时,0可以省略,代表月份的最后一天。 在周字段上表示星期六,相当于 “7” 或 “SAT”。如果在 “L” 前加上数字,则表示该月最后一个星期几。例如在周字段上设置 “6L” 这样的格式,则表示 “本月最后一个星期五”; - W
表示离指定日期的最近那个工作日(默认为周一至周五,你可以重新实现一个函数,然后设计 IsWorkDay 函数指针指向它来个性化工作日设置)。例如在日字段上设置 “15W”,表示离每月 15 号最近的那个工作日触发。如果 15 号正好是周六,则找最近的周五(14号)触发,,如果 15 号是周未,则找最近的下周一(16号)触发。如果15号正好在工作日(周一至周五),则就在该天触发。如果指定格式为 “1W”,它则表示每月 1 号往后最近的工作日触发。如果 1 号正是周六,则将在 3 号下周一触发。(注,”W”前只能设置具体的数字,不允许使用区间 “-”); - #
序号(表示每月的第几个周几),例如在周字段上设置“6#3”,表示在每月的第三个周六。注意如果指定 “n#5”,而正好第五周没有周六,则不会触发该配置(用在母亲节和父亲节再合适不过了) ;
好了,格式的说明也就这样子了,提示下 L 和 W 可以一起组合使用。如果在日字段上设置 LW ,则表示在本月的最后一个工作日触发。
然后我们提供一些简单的掩码示例:
TeX
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
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点59分(整点开始,每隔5分触发)
0 0/5 14,18 * * ? 每天下午的 2点到2点59分、18点到18点59分(整点开始,每隔5分触发)
0 0-5 14 * * ? 每天下午的 2点到2点05分每分触发
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 ? * 6L 每月最后一周的星期六的10点15分触发
0 15 10 ? * 6L 2002-2005 从2002年到2005年每月最后一周的星期六的10点15分触发
0 15 10 ? * 6#3 每月的第三周的星期六开始触发
0 0 12 1/5 * ? 每月的第一个中午开始每隔5天触发一次
0 11 11 11 11 ? 每年的11月11号 11点11分触发(光棍节)
0 0 12,22 ? * W 每个工作日的 12:00:00 或 22:00:00 触发
0 0 12,23 LW * * 每月最后一个工作日的 12:00:00 或 23:00:00 触发
0 0 12,23 L-2W * * 每月最后一天再倒数两天后最近的一个工作日触发
|
如果有写不明白的表达式,可以进群里咨询。
http://blog.qdac.cc/?p=2794
使用 QWorker 做为计划任务引擎的更多相关文章
- csp退役前的做题计划1(真)
csp退役前的做题计划1(真) 因为我太菜了,所以在第一次月考就会退役,还是记录一下每天做了什么题目吧. 任务计划 [ ] Z算法(Z Algorithm) 9.28 [x] ARC061C たくさん ...
- 为什么用B+树做索引&MySQL存储引擎简介
索引的数据结构 为什么不是二叉树,红黑树什么的呢? 首先,一般来说,索引本身也很大,不可能全部存在内存中,因此索引往往以索引文件的方式存在磁盘上.然后一般一个结点一个磁盘块,也就是读一个结点要进行一次 ...
- 思维导图哪款好用?怎么借助MindManager 做旅游计划
世界那么大,想不想去看看!想不想来一场说走就走的旅行?尤其是在新冠的笼罩下, 2020年已经过去四分之三,国内疫情已经基本得到了控制,接下来的日子里你想出门好好玩玩吗? 说走就走的旅游虽然美好,但是你 ...
- ▲教你如何轻易的做linux计划任务▲——小菜一碟
一次性计划任务的安排: at :安排作业在某一时刻执行一次(一般都是用它) batch:安排作业在系统负载不重时执行一次 第一步: #service atd start 开启一次性计划任务 at ...
- 学习计划 mysql 引擎
-- 什么是引擎? 按照我现在的勒戒,就可以提供 Mysql 对不同表的处理方式,各有优缺点. 就像名字一样,把我们数据库看成法拉利的话,引擎也就是发送机,有的跑的快,有的距离长....... -- ...
- 使用QuartZ.net来做定时计划任务 ; 值不能为 null。 参数名: assemblyString
1. 当异常的时候, 发现需要的类名, 没有取到, 然后就发生异常了 2. 分析: 业务层调用数据层, 数据层去掉配置的时候, 发现配置文件中根本就没有配置, 这个时候使用反射来取, 肯定是拿不到的, ...
- [MySQL Reference Manual]14 InnoDB存储引擎
14 InnoDB存储引擎 14 InnoDB存储引擎 14.1 InnoDB说明 14.1.1 InnoDB作为默认存储引擎 14.1.1.1 存储引擎的趋势 14.1.1.2 InnoDB变成默认 ...
- 转载:[转]如何学好3D游戏引擎编程
[转]如何学好3D游戏引擎编程 Albert 本帖被 gamengines 从 游戏引擎(Game Engine) 此文为转载,但是值得一看. 此篇文章献给那些为了游戏编程不怕困难的热血青年,它的 ...
- 关于如何学好游戏3D引擎编程的一些经验[转]
此篇文章献给那些为了游戏编程不怕困难的热血青年,它的神秘要我永远不间断的去挑战自我,超越自我,这样才能攀登到游戏技术的最高峰 ——阿哲VS自己 QQ79134054多希望大家一起交流与沟通 这篇文章是 ...
随机推荐
- 切換 java compiler 版本
有些程式在執行時會顯示需要較新的 java jre 版本, 若系統裝有兩個 java jre 可以使用下列指令切協版本, sudo update-alternatives --config java ...
- The disk contains an unclean file system
Ubuntu : Status 14: The disk contains an unclean file system By mkyong | July 23, 2014 | Viewed : 10 ...
- javascript解决小数的加减乘除精度丢失的方案
原文:http://www.jb51.net/article/85463.htm function accDiv(arg1,arg2){ var t1=0,t2=0,r1,r2; try{t1=arg ...
- 关于toggle的用法
//一个关于鼠标点击 切换场景的代码段 $(document).on('click', '.create-advice-elseparm', function () { $('.advice-else ...
- AC日记——飞行员配对方案问题 洛谷 P2756
题目背景 第二次世界大战时期.. 题目描述 英国皇家空军从沦陷国征募了大量外籍飞行员.由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的2 名飞行员,其中1 名是英国飞行员,另1名是外 ...
- 基于sklearn的分类器实战
已迁移到我新博客,阅读体验更佳基于sklearn的分类器实战 完整代码实现见github:click me 一.实验说明 1.1 任务描述 1.2 数据说明 一共有十个数据集,数据集中的数据属性有全部 ...
- Codeforces 235 C
题目大意 给定一个模板串, 再给出\(n\)个询问, 询问每一个串的循环串总共在原串中出现了多少次. 循环串: 比如说有\(str[] = \{ABCD\}\), 则其循环串有\(\{ABCD\}, ...
- GeoServer自动发布地图服务
1 NetCDF气象文件自动发布案例 GeoServer是一个地理服务器,提供了管理页面进行服务发布,样式,切片,图层预览等一系列操作,但是手动进行页面配置有时并不满足业务需求,所以GeoServer ...
- 一个jdbc connection连接对应一个事务
Spring保证在methodB方法中所有的调用都获得到一个相同的连接.在调用methodB时,没有一个存在的事务,所以获得一个新的连接,开启了一个新的事务. Spring保证在methodB方法中所 ...
- Utuntu 和 window共享文件
由于自己想用服务器跑代码,数据集和模型一般都在本机电脑上,用实验室服务器需要拷贝数据或者,在服务器上重新下载数据很麻烦 都在局域网内可以实现文件共享,代码和数据都在本地,共享给服务器,只需要使用服务器 ...