Net作业调度(三) — Quartz.Net进阶
介绍
前面介绍Quartz.Net的基本用法,但在实际应用中,往往有更多的特性需求,比如记录job执行的执行历史,发邮件等。
阅读目录
- Quartz.Net插件
- TriggerListener,JobListener
- Cron表达式
- Quartz.Net线程池
- 总结
Quartz.Net插件
Quartz.net 自身提供了一个插件接口(ISchedulerPlugin)用来增加附加功能,看下官方定义:
public interface ISchedulerPlugin
{
void Initialize(string pluginName, IScheduler sched);
//关闭调度器
void Shutdown();
//插件启动
void Start();
}
继承接口,实现自己的插件。
public class MyPlugin : ISchedulerPlugin
{
public void Initialize(string pluginName, IScheduler sched)
{
Console.WriteLine("实例化");
}
public void Start()
{
Console.WriteLine("启动");
}
public void Shutdown()
{
Console.WriteLine("关闭");
}
}
主函数里面配置要实现的插件,注释部分,一句话搞定。
static void Main(string[] args)
{
var properties = new NameValueCollection();
//MyPlugin 自定义名称。 "命名空间.类名,程序名称"
properties["quartz.plugin.MyPlugin.type"] = "QuartzDemo3.MyPlugin,QuartzDemo3";
var schedulerFactory = new StdSchedulerFactory(properties);
var scheduler = schedulerFactory.GetScheduler();
var job = JobBuilder.Create<HelloJob>()
.WithIdentity("myJob", "group1")
.Build();
var trigger = TriggerBuilder.Create()
.WithIdentity("mytrigger", "group1")
.WithCronSchedule("/2 * * ? * *")
.Build();
scheduler.ScheduleJob(job, trigger);
scheduler.Start();
Thread.Sleep(6000);
scheduler.Shutdown(true);
Console.ReadLine();
}
运行结果如下:
TriggerListener,JobListener
这2个是对触发器和job本身的行为监听器,这样更好方便跟踪Job的状态及运行情况。
ITriggerListener是官方定义的接口,这里我们直接继承实现。
public class MyTriggerListener : ITriggerListener
{
private string name;
public void TriggerComplete(ITrigger trigger, IJobExecutionContext context, SchedulerInstruction triggerInstructionCode)
{
Console.WriteLine("job完成时调用");
}
public void TriggerFired(ITrigger trigger, IJobExecutionContext context)
{
Console.WriteLine("job执行时调用");
}
public void TriggerMisfired(ITrigger trigger)
{
Console.WriteLine("错过触发时调用(例:线程不够用的情况下)");
}
public bool VetoJobExecution(ITrigger trigger, IJobExecutionContext context)
{
//Trigger触发后,job执行时调用本方法。true即否决,job后面不执行。
return false;
}
public string Name { get { return name; } set { name = value; } }
}
主函数添加:
//添加监听器到指定的trigger
scheduler.ListenerManager.AddTriggerListener(myJobListener, KeyMatcher<TriggerKey>.KeyEquals(new TriggerKey("mytrigger", "group1")));
////添加监听器到指定分类的所有监听器。
//scheduler.ListenerManager.AddTriggerListener(myJobListener, GroupMatcher<TriggerKey>.GroupEquals("myJobGroup"));
////添加监听器到指定分类的所有监听器。
//scheduler.ListenerManager.AddTriggerListener(myJobListener, GroupMatcher<TriggerKey>.GroupEquals("myJobGroup"));
////添加监听器到指定的2个分组。
//scheduler.ListenerManager.AddTriggerListener(myJobListener, GroupMatcher<TriggerKey>.GroupEquals("myJobGroup"), GroupMatcher<TriggerKey>.GroupEquals("myJobGroup2"));
////添加监听器到所有的触发器上。
//scheduler.ListenerManager.AddTriggerListener(myJobListener, GroupMatcher<TriggerKey>.AnyGroup());
scheduler.Start();
JobListener同理,这里不多做描述。
Cron表达式
quartz中的cron表达式和Linux下的很类似,比如 "/5 * * ? * * *" 这样的7位表达式,最后一位年非必选。
表达式从左到右,依此是秒、分、时、月第几天、月、周几、年。下面表格是要遵守的规范:
字段名 |
允许的值 |
允许的特殊字符 |
---|---|---|
Seconds |
0-59 |
, - * / |
Minutes |
0-59 |
, - * / |
Hours |
0-23 |
, - * / |
Day of month |
1-31 |
, - * ? / L W |
Month |
1-12 or JAN-DEC |
, - * / |
Day of week |
1-7 or SUN-SAT |
, - * ? / L # |
Year |
空, 1970-2099 |
, - * / |
特殊字符 |
解释 |
---|---|
, |
或的意思。例:分钟位 5,10 即第5分钟或10分都触发。 |
/ |
a/b。 a:代表起始时间,b频率时间。 例; 分钟位 3/5, 从第三分钟开始,每5分钟执行一次。 |
* |
频率。 即每一次波动。 例;分钟位 * 即表示每分钟 |
- |
区间。 例: 分钟位 5-10 即5到10分期间。 |
? |
任意值 。 即每一次波动。只能用在DayofMonth和DayofWeek,二者冲突。指定一个另一个一个要用? |
L |
表示最后。 只能用在DayofMonth和DayofWeek,4L即最后一个星期三 |
W |
工作日。 表示最后。 只能用在DayofWeek |
# |
4#2。 只能用DayofMonth。 某月的第二个星期三 |
实例介绍
”0 0 10,14,16 * * ?" 每天10点,14点,16点 触发。
"0 0/5 14,18 * * ?" 每天14点或18点中,每5分钟触发 。
"0 4/15 14-18 * * ?" 每天14点到18点期间, 从第四分钟触发,每15分钟一次。
"0 15 10 ? * 6L" 每月的最后一个星期五上午10:15触发。
Quartz.Net线程池
线程池数量设置:
properties["quartz.threadPool.threadCount"] = "5";
这个线程池的设置,是指同时间,调度器能执行Job的最大数量。
quartz是用每个线程跑一个job。上面的设置可以解释是job并发时能执行5个job,剩下的job如果触发时间恰好到了,当前job会进入暂停状态,直到有可用的线程。
如果在指定的时间范围依旧没有可用线程,会触发misfired时间。
quartz 提供了IThreadPool接口,也可以用自定义线程池来实现。
配置如下:
properties["quartz.threadPool.type"] = "Quartz.Simpl.SimpleThreadPool, Quartz";
一般来说作业调度很少并发触发大量job,如果有上百个JOB,可在服务器承受范围内适量增加线程数量。
总结
官方有LoggingTriggerHistoryPlugin,LoggingJobHistoryPlugin 已实现的,触发器和job历史记录的插件。
Quartz.Plugin 命名空间下有官方实现的其他一些插件,也可以自己增加扩展。
quartz中监听器还有SchedulerListener,使用方法基本一样。
本文基于自用经验和官方文档代码来写的,部分是直接翻译的。
Quartz.Net官方教程http://www.quartz-scheduler.net/documentation/quartz-2.x/tutorial/index.html
- POJ 2311 Cutting Game(二维SG+Multi-Nim)
- js去掉html标签和去掉字符串文本的所有的空格
- php操作memcache的使用测试总结
- linux awk命令详解
- php str_split 解决中文
- PHP汉字转拼音函数
- 51NOD 1185 威佐夫游戏 V2(威佐夫博弈)
- HDU 1527 取石子游戏(威佐夫博弈)
- PHP文件操作类
- Linux添加/删除用户和用户组
- 次小生成树
- HDU 4786Fibonacci Tree(最小生成树)
- HDU 1847 Good Luck in CET-4 Everybody!(找规律版巴什博奕)
- HDU 4764 Stone(巴什博奕)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Android编程实现对话框Dialog背景透明功能示例
- Android开发中DatePicker日期与时间控件实例代码
- Android Shader应用开发之霓虹闪烁文字效果
- Android中ToggleButton开关状态按钮控件使用方法详解
- 零基础学小程序005---小程序登陆注册功能实现
- Android RecyclerView 复用错乱通用解法详解
- Android把Bitmap保存为PNG图像文件的简单代码
- 零基础学小程序006---小程序获取用户信息用户昵称
- Android webview 内存泄露的解决方法
- Android编程实现全局获取Context及使用Intent传递对象的方法详解
- Android App更改应用的图标的实现方法
- 零基础学小程序007---小程序获取用户openid
- Android编程中光线传感器的调用方法详解
- Android编程使用sax解析xml数据的方法详解
- 微信小程序弹出用户授权弹窗,微信小程序引导用户授权,获取位置经纬度