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") 来还是要有趣些.当 ...
随机推荐
- Python 装饰器初探
Python 装饰器初探 在谈及Python的时候,装饰器一直就是道绕不过去的坎.面试的时候,也经常会被问及装饰器的相关知识.总感觉自己的理解很浅显,不够深刻.是时候做出改变,对Python的装饰器做 ...
- HTTPS和HTTP的区别:
https协议需要到ca申请证书,一般免费证书很少,需要交费.http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议http和https使用的是完全不同的连接方式用的 ...
- 【bzoj2038】[2009国家集训队]小Z的袜子(hose) 莫队算法
原文地址:http://www.cnblogs.com/GXZlegend/p/6803860.html 题目描述 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终 ...
- 【Luogu】P2465山贼集团(树形状压DP)
题目链接 写了个70分暴力还挂了,第一遍提交只拿了十分……海星 首先建虚拟节点多叉树转成二叉,然后子集枚举DP 设g[x][i]是以x为根的子树内山贼集合i,x啥都不选也没贡献的时候的最大价值 f[x ...
- 在浏览器中进行深度学习:TensorFlow.js (八)生成对抗网络 (GAN
Generative Adversarial Network 是深度学习中非常有趣的一种方法.GAN最早源自Ian Goodfellow的这篇论文.LeCun对GAN给出了极高的评价: “There ...
- Reinstall msdtc on Windows
Reinstall MSDTC The system reported an unexpected error condition. You can resolve this condition by ...
- sublime 设置代码片段不起作用的问题
最近爱上了sublime 但是我也继续爱我的Vscode 安装sublime代码片段的时候,遇到了设置好的代码片段按 Tab建 不起作用的问题.快折磨死的时候灵光一闪: 首先检查设置的代码片段 &l ...
- log4net日志分割,按大小分割
最近写了一个socket通信的手表在线服务端,在日志方面,记录下Log4net日志分割 1.引入log4net.dll 2.web.config添加configsection handler 映射: ...
- Socket学习进阶之基础通信
服务端代码: using System; using System.Text; using System.Net; using System.Net.Sockets; public class ser ...
- [ CodeVS冲杯之路 ] P3116
不充钱,你怎么AC? 题目:http://codevs.cn/problem/3116/ 基础的高精度加法,注意一下两个数长短不一和答案第一位的处理即可,当然也可以用压位的方法做 #include&l ...