Lazy Scheduler:我的轻量级任务调度框架
一、背景
工作中经常涉及任务调度,一直都是采用while(true) => if hitted DO => Thread.Sleep(interval)的模式。但是最近实在是感觉这种实现模式很挫。并且没有考虑到性能问题,需要撞击n次才能命中一次,使用效率不足5%(一百次while循环命中不到5次),但是单方面加大线程睡眠时间又无法保证高准确性和高精度。那有么有其它好的思路:即可以保持高准确性、高精度,又不浪费资源呢?
二、我的思路
上述的短板在于:无目的的线程Sleep,如果我们可以每次恰到好处的Sleep,即线程被唤醒后刚好赶上下一次的任务到来,命中率就是100%了嘛。所以可以这样做:进入While后先按照Scheduler计算出下次的运行时间距离现在还有多久(Interval),然后直接Sleep(Interval),等待线程唤醒后就立即执行下一个既定Task就可以了。那这样做唯一的难点就在于你的Scheduler是否可计算、是否可以计算出下一次的运行时间点。
还好,我碰到的逻辑都还是满足这一点需求的:
(1)每隔一段时间执行一次的计划任务;
(2)在指定时间点必须执行的计划任务;
其他人性化设定:周六周日不运行。
三、代码实现
(1)主要有:负责调度的接口:IScheduler;Scheduler设定:ISchedulerSetting;任务接口:ITask以及一些其他的辅助类。
(2)难点:计算Interval的实现类:FixTimeSchedulerSetting.cs和IntervalSchedulerSetting.cs
- //Author: night-king
- // Email: deepleo@163.com
- //Home: http://deepleo.com
- //Github: https://github.com/night-king/
- //Date: 2013-11-1
- //Place: Wuhan@China
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Collections;
- namespace Deepleo.LazyScheduler.Setting
- {
- public class FixTimeSchedulerSetting : IFixTimeSchedulerSetting, IWeekSchedulerSetting
- {
- public IList<DayOfWeek> ExcludeWeeks
- {
- get;
- set;
- }
- public int Hour
- {
- get;
- set;
- }
- public int Minutes
- {
- get;
- set;
- }
- public int Second
- {
- get;
- set;
- }
- public FixTimeSchedulerSetting(IList<DayOfWeek> excludeWeeks)
- {
- ExcludeWeeks = excludeWeeks;
- }
- public virtual TimeSpan CalculateNext()
- {
- var nowDateTime = System.DateTime.Now;
- var expectNextTime = System.DateTime.Parse(string.Format("{0}-{1}-{2} {3}:{4}:{5}", nowDateTime.Year, nowDateTime.Month, nowDateTime.Day, Hour, Minutes, Second));
- var todayWeek = nowDateTime.DayOfWeek;
- var km = new WeekManager(ExcludeWeeks);
- var delayDays = km.CalculateDelayDays(todayWeek);
- if (delayDays == 0)// this day of week can do
- {
- if (expectNextTime > nowDateTime) return expectNextTime - nowDateTime;
- else delayDays++;
- }
- return expectNextTime.AddDays(delayDays) - nowDateTime;
- }
- }
- }
- using System;
- using System.Collections.Generic;
- using System.Text;
- namespace Deepleo.LazyScheduler.Setting
- {
- public class IntervalSchedulerSetting : IIntervalSchedulerSetting, IWeekSchedulerSetting
- {
- public TimeSpan Interval
- {
- get;
- set;
- }
- public IList<DayOfWeek> ExcludeWeeks
- {
- get;
- set;
- }
- public IntervalSchedulerSetting(IList<DayOfWeek> excludeWeeks)
- {
- ExcludeWeeks = excludeWeeks;
- }
- public TimeSpan CalculateNext()
- {
- var nowDateTime = System.DateTime.Now;
- var todayWeek =nowDateTime.DayOfWeek;
- var km = new WeekManager(ExcludeWeeks);
- var delayDays = km.CalculateDelayDays(todayWeek);
- var interval = Interval.Add(new TimeSpan(delayDays, 0, 0, 0));
- if (interval.CompareTo(new TimeSpan(0, 0, 1)) <= 0) return new TimeSpan(0, 0, 1);
- else return interval;
- }
- }
- }
重要的辅助类:WeekManager的实现代码:
- //Author: night-king
- // Email: deepleo@163.com
- //Home: http://deepleo.com
- //Github: https://github.com/night-king/
- //Date: 2013-11-1
- //Place: Wuhan@China
- using System;
- using System.Collections.Generic;
- using System.Text;
- namespace Deepleo.LazyScheduler.Setting
- {
- public class WeekManager
- {
- private Dictionary<int, DayOfWeek> _allowWeekDict;
- public WeekManager(IList<DayOfWeek> notAllowWeeks)
- {
- _allowWeekDict = new Dictionary<int, DayOfWeek>();
- if (!notAllowWeeks.Contains(DayOfWeek.Sunday))
- _allowWeekDict.Add(0, DayOfWeek.Sunday);
- if (!notAllowWeeks.Contains(DayOfWeek.Monday))
- _allowWeekDict.Add(1, DayOfWeek.Monday);
- if (!notAllowWeeks.Contains(DayOfWeek.Tuesday))
- _allowWeekDict.Add(2, DayOfWeek.Tuesday);
- if (!notAllowWeeks.Contains(DayOfWeek.Wednesday))
- _allowWeekDict.Add(3, DayOfWeek.Wednesday);
- if (!notAllowWeeks.Contains(DayOfWeek.Thursday))
- _allowWeekDict.Add(4, DayOfWeek.Thursday);
- if (!notAllowWeeks.Contains(DayOfWeek.Friday))
- _allowWeekDict.Add(5, DayOfWeek.Friday);
- if (!notAllowWeeks.Contains(DayOfWeek.Saturday))
- _allowWeekDict.Add(6, DayOfWeek.Saturday);
- }
- /// <summary>
- /// Calcute how many delay days
- /// </summary>
- /// <param name="week">current day of week</param>
- /// <returns>delay days</returns>
- public int CalculateDelayDays(DayOfWeek week)
- {
- var weekOfDay = (int)week;
- int distence = 0;
- while (true)
- {
- if (_allowWeekDict.ContainsKey(weekOfDay))
- {
- return distence;
- }
- else
- {
- weekOfDay = weekOfDay < 6 ? weekOfDay + 1 : 0;
- distence++;
- }
- }
- }
- }
- }
四、测试
(1)5s钟时间间隔的测试结果:
(2)1s测试结果:
再看CPU占用情况:
基本上稳定在0%,内存占用也只有6.4k.
五、代码下载:
http://files.cnblogs.com/deepleo/SchedulerSolution.zip
https://github.com/night-king/LazyScheduler
Lazy Scheduler:我的轻量级任务调度框架的更多相关文章
- Lazy Scheduler
Lazy Scheduler:我的轻量级任务调度框架 一.背景 工作中经常涉及任务调度,一直都是采用while(true) => if hitted DO => Thread.Slee ...
- SpringBoot官方支持任务调度框架,轻量级用起来也挺香!
大家好,我是二哥呀.定时任务的应用场景其实蛮常见的,比如说: 数据备份 订单未支付则自动取消 定时爬取数据 定时推送信息 定时发布文章 等等(想不出来了,只能等等来凑,,反正只要等的都需要定时,怎么样 ...
- 企业级任务调度框架Quartz(6) 任务调度器(Scheduler)
前序: 我们已经在前面的内容能里看到了,我们用 Scheduler 来管理我们的 Job:创建并关联触发器以使 Job 能被触发执行:以及如可选择 calendar 为给定的时程安排提供更多 ...
- Java任务调度框架Quartz入门
Quartz[kwɔːts]:石英,其框架和名字一样简单朴素又不失魅力,在Java程序界,Quartz大名鼎鼎,很多Java应用几乎都集成或构建了一个定时任务调度系统,Quartz是一个定时任务调度框 ...
- APScheduler轻量级定时任务框架
目录 一.APScheduler简介 支持的后端存储作业 集成的Python框架 二.APScheduler下载安装 三.APScheduler组件 各组件简介 调度器 作业存储器 执行器 触发器 四 ...
- Quarzt.NET 任务调度框架
Quartz.NET是一个开源的作业调度框架,是 OpenSymphony 的 Quartz API 的.NET移植,它用C#写成,可用于winform和asp.net应用中.它提供了巨大的灵活性 ...
- Quartz:不要重复造轮子,一款企业级任务调度框架。
背景 第一次遇到定时执行某些任务的需求时,很多朋友可能设计了一个小类库,这个类图提高了一个接口,然后由调度器调度所有注册的接口类型,我就是其中之一,随着接触的开源项目越来越多,我的某些开发习惯受到了影 ...
- 企业级任务调度框架Quartz(8) 线程在Quartz里的意义(2)
前序: 做为企业里的任务调度框架,出现同一时间点同时运行两个任务,或者两个任务因为开始的执行时间和执行时间的长短,很有可能出现任务并发执行的情况:因为Quartz的实现是采用java编程,那 ...
- 企业级任务调度框架Quartz(3) 一个简单的Quartz 例子
1. 一个简单的Quartz 工程 本示例应用比起众所周知的 System.out.println("Hello world from Quartz") 来还是要有趣些.当 ...
随机推荐
- hdu2010(dfs+剪枝)
Tempter of the Bone Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Othe ...
- asp+access win2008php+mysql /dedecms 配置总结
1. IIS 应用池 高级设置 启用32位应用程序:True 2. c盘window/Temp user 应该有管理权限 如果不行 creator owner 给予修改权限 ...
- Windows域同步检查repadmin
C:\Users\>repadmin /show replUsage: repadmin <cmd> <args> [/u:{domain\user}] [/pw:{pa ...
- css去掉点击连接时所产生的虚线边框技巧兼容符合w3c标准的浏览器
解决方法: 1.在css中加上outline:none; 代码如下: a.fontnav { text-align:left;color:#555; text-decoration:none; out ...
- 飞镖(bzoj 2335)
Description 飞镖是在欧洲颇为流行的一项运动.它的镖盘上分为20个扇形区域,分别标有1到20的分值,每个区域中有单倍.双倍和三倍的区域,打中对应的区域会得到分值乘以倍数所对应的分数.例如打中 ...
- Handler 源码分析
Handler用法: 无参 Handler 构造函数实例化一个 Handler 类型的全局变量,并重写其 handleMessage 方法,在某一方法内调用 Handler 的 sendEmptyMe ...
- 自己写的enum转换的一个扩展,
public static String ToEnumName(this int? source, Type e) { if (!source.HasValue) throw new Argument ...
- 行为型设计模式之策略模式(Strategy)
结构 意图 定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换.本模式使得算法可独立于使用它的客户而变化. 适用性 许多相关的类仅仅是行为有异.“策略”提供了一种用多个行为中的一个行为来配 ...
- error LNK2001: unresolved external symbol "int g_cTemplates" (?g_cTemplates@@3HA)(转)
原文转自:http://blog.sina.com.cn/s/blog_639a2ad70101kpen.html 编译directshow若干问题的解决 1.安装好windows sdk,进入dir ...
- http模拟登录
= =其实很简单,写这个的目的呢,是为了练习下Ruby而已 就是post到登录地址,得到cookie,然后以后的请求都用这个cookie就好了. require 'net/http' module E ...