亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.430618.com 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

關于時間輪算法的起始

我也認真的看了時間輪算法相關,大致都是如下的一個圖

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述 個人認為的問題

大部分文章在解釋這個為何用時間輪的時候都再說

 

為什么要用時間輪實現

  1. 1. 通常用于實現linux內核任務、游戲類的buf計時。
  2. 2. 單個時間輪局限性:保存的任務數量少,不能超過當前時間輪。
  3. 3. 多層時間輪,典型:日-時-分-秒
  4. 4. 傳統JAVA實現定時:Timer,只能單線程,會阻塞;Executors.newScheduledThreadPoll, 使用的最小堆來實現,任務還是不能太多,添加時間復雜度為O(logn)

時間輪定時器最大的優點

  1. 1. 是任務的添加與移除,都是O(1)級的復雜度;
  2. 2. 不會占用大量的資源;
  3. 3. 只需要有一個線程去推進時間輪就可以工作了
 
privateTask[很長] tasks;

publicList<Task> getTaskList( longtimestamp) {

returntask. get(timestamp)

}

// 假裝這里真的能一毫秒一個循環

publicvoidrun{

while( true){

getTaskList(System.currentTimeMillis).后臺執行

Thread.sleep( 1);

}

}

假如這個數組長度達到了億億級,我們確實可以這么干。那如果將精度縮減到秒級呢?我們也需要一個百億級長度的數組。

先不說內存夠不夠,顯然你的定時器要這么大的內存顯然很浪費。

基于個人的理解對其進行改造和實現

對于以上的描述,我自己還是很不認同的,我為啥要聲明這么大的數組,難道不能有一個任務,我就放一個任務么,實際數組的長度應該是你任務數的長度吧。

要不然,為啥要這么浪費。想不通,可能還有別的解釋,誰有答案可以告訴我。

在實際的使用中,一般都為秒級,毫秒級都很少,因為毫秒級的不準。

所以,我可以根據這些通過hash字典構建一個 這樣的時間輪算法,也作為我自己想實現定時任務框架的一部分。

邏輯:核心為一個字典,key 為時間戳,值為任務列表。整體就是每個添加的任務都有一個觸發的時間(秒),到了這個秒,時間就會觸發,自然會去執行相關的任務。有了任務才會添加,不會任何任務都添加的。任務觸發的時候,會獲取任務下一次執行的時間,并插入到任務列表里。

static void Main( string[] args)

{

ScheduledTask scheduledTask = newScheduledTask( => { Console.WriteLine( $" {DateTime.Now}" ); }, newTimeSpan( 0, 0, 5));

TimeWheel timeWheel = newTimeWheel;

timeWheel.AddTask(scheduledTask);

timeWheel.Run;

Console.WriteLine( "開始運行時間輪!");

Console.ReadLine;

} ///<summary>

///時間輪算法(終極)實現

///大部分都是支持秒級,所以,按照秒級進行實現

///</summary>

publicclassTimeWheel

{

///<summary>

///任務列表

///</summary>

publicConcurrentDictionary< long, List<IScheduledTask>> Tasks = new;

publicvoidRun

{

while( true)

{

varnow = DateTime.Now;

Task.Run( => { Trigger(now); });

varoffset = 500- now.Millisecond;

SpinWait.SpinUntil( => false, 1000+ offset);

}

}

publicvoidTrigger(DateTime dateTime)

{

vartimeStamp = GenerateTimestamp(dateTime);

varoldTimeStamp = timeStamp - 1;

Tasks.TryRemove(oldTimeStamp, outvar_);

Tasks.TryGetValue(timeStamp, outvarresult);

if(result?.Any == true)

{

foreach( varitem inresult)

{

Task.Run(item.GetAction);

varNewTime = item.GetNextTime;

if(NewTime.HasValue)

{

AddTask(NewTime.Value, item);

}

}

}

}

publicvoidAddTask(IScheduledTask scheduledTask)

{

vartimeStamp = GenerateTimestamp(scheduledTask.GetNextTime.Value);

Tasks.AddOrUpdate(timeStamp, newList<IScheduledTask> { scheduledTask }, (k, v) =>

{

v.Add(scheduledTask);

returnv;

});

}

publicvoidAddTask(DateTime dateTime, IScheduledTask scheduledTask)

{

vartimeStamp = GenerateTimestamp(dateTime);

Tasks.AddOrUpdate(timeStamp, newList<IScheduledTask> { scheduledTask }, (k, v) =>

{

v.Add(scheduledTask);

returnv;

});

}

privatelongGenerateTimestamp(DateTime dateTime)

{

returnnewDateTimeOffset(dateTime.ToUniversalTime).ToUnixTimeSeconds;

}

privateDateTime GetDatetime( longtimeStamp)

{

vard = DateTimeOffset.FromUnixTimeSeconds(timeStamp);

returnd.LocalDateTime;

}

} publicinterfaceIScheduledTask

{

publicAction GetAction;

publicDateTime? GetNextTime;

}

///<summary>

///定時器任務,普通任務

///間隔指定的時間

///</summary>

publicclassScheduledTask: IScheduledTask

{

privateAction _action;

privateTimeSpan timeSpan;

publicScheduledTask(Action action, TimeSpan timeSpan)

{

this._action = action;

this.timeSpan = timeSpan;

}

publicAction GetAction

{

returnthis._action;

}

publicDateTime? GetNextTime

{

returnDateTime.Now.AddSeconds(timeSpan.TotalSeconds);

}

}

最后的效果

在這里插入圖片描述

當然,也可以通過CRON表達式來實現更為高級的。

后期再來個更高級一點的。 github地址

https://github.com/kesshei/TimeWheelDemo

分享到:
標簽:Net
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定