太原网站开发模板,无锡开发公司,代做硬件毕业设计网站,前端课程网站关于时间轮算法的起始我也认真的看了时间轮算法相关#xff0c;大致都是如下的一个图在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述个人认为的问题大部分文章在解释这个为何用时间轮的时候都再说假设我们现在有一个很大的数组#xff0c;专门用… 关于时间轮算法的起始我也认真的看了时间轮算法相关大致都是如下的一个图在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述个人认为的问题大部分文章在解释这个为何用时间轮的时候都再说假设我们现在有一个很大的数组专门用于存放延时任务。它的精度达到了毫秒级那么我们的延迟任务实际上需要将定时的那个时间简单转换为毫秒即可然后将定时任务存入其中比如说当前的时间是2018/10/24 19:43:45那么就将任务存入Task[1540381425000]value则是定时任务的内容。假如这个数组长度达到了亿亿级我们确实可以这么干。那如果将精度缩减到秒级呢我们也需要一个百亿级长度的数组。先不说内存够不够显然你的定时器要这么大的内存显然很浪费。为什么要用时间轮实现1. 通常用于实现linux内核任务、游戏类的buf计时。2. 单个时间轮局限性保存的任务数量少不能超过当前时间轮。3. 多层时间轮典型日-时-分-秒4. 传统java实现定时Timer只能单线程会阻塞Executors.newScheduledThreadPoll, 使用的最小堆来实现任务还是不能太多添加时间复杂度为O(logn)时间轮定时器最大的优点1. 是任务的添加与移除都是O(1)级的复杂度2. 不会占用大量的资源3. 只需要有一个线程去推进时间轮就可以工作了举例说明比如说当前的时间是2018/10/24 19:43:45那么就将任务存入Task[1540381425000]value则是定时任务的内容。private Task[很长] tasks;
public ListTask getTaskList(long timestamp) {return task.get(timestamp)
}
// 假装这里真的能一毫秒一个循环
public void run(){while (true){getTaskList(System.currentTimeMillis()).后台执行()Thread.sleep(1);}
}假如这个数组长度达到了亿亿级我们确实可以这么干。那如果将精度缩减到秒级呢我们也需要一个百亿级长度的数组。先不说内存够不够显然你的定时器要这么大的内存显然很浪费。基于个人的理解对其进行改造和实现对于以上的描述我自己还是很不认同的我为啥要声明这么大的数组难道不能有一个任务我就放一个任务么实际数组的长度应该是你任务数的长度吧。要不然为啥要这么浪费。想不通可能还有别的解释谁有答案可以告诉我。在实际的使用中一般都为秒级毫秒级都很少因为毫秒级的不准。所以我可以根据这些通过hash字典构建一个 这样的时间轮算法也作为我自己想实现定时任务框架的一部分。逻辑核心为一个字典key 为时间戳值为任务列表。整体就是每个添加的任务都有一个触发的时间秒到了这个秒时间就会触发自然会去执行相关的任务。有了任务才会添加不会任何任务都添加的。任务触发的时候会获取任务下一次执行的时间并插入到任务列表里。static void Main(string[] args){ScheduledTask scheduledTask new ScheduledTask(() { Console.WriteLine(${DateTime.Now}); }, new TimeSpan(0, 0, 5));TimeWheel timeWheel new TimeWheel();timeWheel.AddTask(scheduledTask);timeWheel.Run();Console.WriteLine(开始运行时间轮!);Console.ReadLine();}/// summary/// 时间轮算法(终极)实现/// 大部分都是支持秒级所以按照秒级进行实现/// /summarypublic class TimeWheel{/// summary/// 任务列表/// /summarypublic ConcurrentDictionarylong, ListIScheduledTask Tasks new();public void Run(){while (true){var now DateTime.Now;Task.Run(() { Trigger(now); });var offset 500 - now.Millisecond;SpinWait.SpinUntil(() false, 1000 offset);}}public void Trigger(DateTime dateTime){var timeStamp GenerateTimestamp(dateTime);var oldTimeStamp timeStamp - 1;Tasks.TryRemove(oldTimeStamp, out var _);Tasks.TryGetValue(timeStamp, out var result);if (result?.Any() true){foreach (var item in result){Task.Run(item.GetAction());var NewTime item.GetNextTime();if (NewTime.HasValue){AddTask(NewTime.Value, item);}}}}public void AddTask(IScheduledTask scheduledTask){var timeStamp GenerateTimestamp(scheduledTask.GetNextTime().Value);Tasks.AddOrUpdate(timeStamp, new ListIScheduledTask() { scheduledTask }, (k, v) {v.Add(scheduledTask);return v;});}public void AddTask(DateTime dateTime, IScheduledTask scheduledTask){var timeStamp GenerateTimestamp(dateTime);Tasks.AddOrUpdate(timeStamp, new ListIScheduledTask() { scheduledTask }, (k, v) {v.Add(scheduledTask);return v;});}private long GenerateTimestamp(DateTime dateTime){return new DateTimeOffset(dateTime.ToUniversalTime()).ToUnixTimeSeconds();}private DateTime GetDatetime(long timeStamp){var d DateTimeOffset.FromUnixTimeSeconds(timeStamp);return d.LocalDateTime;}}public interface IScheduledTask{public Action GetAction();public DateTime? GetNextTime();}/// summary/// 定时器任务普通任务/// 间隔指定的时间/// /summarypublic class ScheduledTask : IScheduledTask{private Action _action;private TimeSpan timeSpan;public ScheduledTask(Action action, TimeSpan timeSpan){this._action action;this.timeSpan timeSpan;}public Action GetAction(){return this._action;}public DateTime? GetNextTime(){return DateTime.Now.AddSeconds(timeSpan.TotalSeconds);}}最后的效果在这里插入图片描述当然也可以通过CRON表达式来实现更为高级的。后期再来个更高级一点的。github地址https://github.com/kesshei/TimeWheelDemo