使用 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多希望大家一起交流与沟通 这篇文章是 ...
随机推荐
- docker mysql 导入导出数据
导出数据 1.导出mysql单张表结构和数据: docker exec -it my-mysql mysqldump dbname -uroot -p123456 --tables tname > ...
- python,django,mysql学习之环境安装配置
参考:https://docs.djangoproject.com/en/1.6/intro/tutorial01/ http://rainyang.blog.51cto.com/469543/115 ...
- 不要使用 reader.Peek() 去读取每行数据
1.问题描述 使用SteamRead的Peek()和ReadLine()来读取流中的数据,如果数据行数太多,会读取不完整(后面有些数据就读不出来了). 比如: while (srResponseRea ...
- BZOJ 1044 木棍分割(二分答案 + DP优化)
题目链接 木棍分割 1044: [HAOI2008]木棍分割 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3830 Solved: 1453[S ...
- 【IOI2014】Game
题目简述 健佳是一个喜欢做游戏的小男生.当有人问问题时,他更喜欢通过玩游戏的方式作答,而不是直接回答.健佳碰到了他的朋友梅玉,跟她讲了台湾的航空网.在台湾有 $n$ 个城市(编号为 $0, \dots ...
- 第4章 CentOS软件安装
一.安装JDK 1.1 卸载旧版JDK 首先,在你的服务器上运行一下更新. yum update 然后,在您的系统上搜索,任何版本的已安装的JDK组件. rpm -qa | grep -E '^ope ...
- 【CSS】使用CSS控制文字过多自动省略号
使用CSS可以设置一下样式: <style> u,small{ overflow: hidden; text-overflow: ellipsis; display: -webkit-bo ...
- Oracle 11g客户端
资源 下载资源,直接解压进行配置 Oracle官方资源:http://www.oracle.com/technetwork/database/features/instant-client/index ...
- Odoo(OpenERP)开发实践:通过XML-RPC接口訪问Odoo数据库
Odoo(OpenERP)server支持通过XML-RPC接口訪问.操作数据库,基于此可实现与其它系统的交互与集成. 本文是使用Java通过XMLRPC接口操作Odoo数据库的简单演示样例.本例引用 ...
- 编写自己的UDTF
1. UDTF介绍 UDTF(User-Defined Table-Generating Functions) 用来解决 输入一行输出多行(On-to-many maping) 的需求. 2. 编写自 ...