golang 實現延遲訊息原理與方法
package main; import ( "time" "errors" "fmt" ) //延遲訊息 type DelayMessage struct { //當前下標 curIndex int; //環形槽 slots [3600]map[string]*Task; //關閉 closed chan bool; //任務關閉 taskClose chan bool; //時間關閉 timeClose chan bool; //啟動時間 startTime time.Time; } //執行的任務函式 type TaskFunc func(args ...interface{}); //任務 type Task struct { //迴圈次數 cycleNum int; //執行的函式 exec TaskFunc; params []interface{}; } //建立一個延遲訊息 func NewDelayMessage() *DelayMessage { dm := &DelayMessage{ curIndex: 0, closed: make(chan bool), taskClose: make(chan bool), timeClose: make(chan bool), startTime: time.Now(), }; for i := 0; i < 3600; i++ { dm.slots[i] = make(map[string]*Task); } return dm; } //啟動延遲訊息 func (dm *DelayMessage) Start() { go dm.taskLoop(); go dm.timeLoop(); select { case <-dm.closed: { dm.taskClose <- true; dm.timeClose <- true; break; } }; } //關閉延遲訊息 func (dm *DelayMessage) Close() { dm.closed <- true; } //處理每1秒的任務 func (dm *DelayMessage) taskLoop() { defer func() { fmt.Println("taskLoop exit"); }(); for { select { case <-dm.taskClose: { return; } default: { //取出當前的槽的任務 tasks := dm.slots[dm.curIndex]; if len(tasks) > 0 { //遍歷任務,判斷任務迴圈次數等於0,則執行任務 //否則任務迴圈次數減1 for k, v := range tasks { if v.cycleNum == 0 { go v.exec(v.params...); //刪除執行過的任務 delete(tasks, k); } else { v.cycleNum--; } } } } } } } //處理每1秒移動下標 func (dm *DelayMessage) timeLoop() { defer func() { fmt.Println("timeLoop exit"); }(); tick := time.NewTicker(time.Second); for { select { case <-dm.timeClose: { return; } case <-tick.C: { fmt.Println(time.Now().Format("2006-01-02 15:04:05")); //判斷當前下標,如果等於3599則重置為0,否則加1 if dm.curIndex == 3599 { dm.curIndex = 0; } else { dm.curIndex++; } } } } } //新增任務 func (dm *DelayMessage) AddTask(t time.Time, key string, exec TaskFunc, params []interface{}) error { if dm.startTime.After(t) { return errors.New("時間錯誤"); } //當前時間與指定時間相差秒數 subSecond := t.Unix() - dm.startTime.Unix(); //計算迴圈次數 cycleNum := int(subSecond / 3600); //計算任務所在的slots的下標 ix := subSecond % 3600; //把任務加入tasks中 tasks := dm.slots[ix]; if _, ok := tasks[key]; ok { return errors.New("該slots中已存在key為" + key + "的任務"); } tasks[key] = &Task{ cycleNum: cycleNum, exec: exec, params: params, }; return nil; } func main() { //建立延遲訊息 dm := NewDelayMessage(); //新增任務 dm.AddTask(time.Now().Add(time.Second*10), "test1", func(args ...interface{}) { fmt.Println(args...); }, []interface{}{1, 2, 3}); dm.AddTask(time.Now().Add(time.Second*10), "test2", func(args ...interface{}) { fmt.Println(args...); }, []interface{}{4, 5, 6}); dm.AddTask(time.Now().Add(time.Second*20), "test3", func(args ...interface{}) { fmt.Println(args...); }, []interface{}{"hello", "world", "test"}); dm.AddTask(time.Now().Add(time.Second*30), "test4", func(args ...interface{}) { sum := 0; for arg := range args { sum += arg; } fmt.Println("sum : ", sum); }, []interface{}{1, 2, 3}); //40秒後關閉 time.AfterFunc(time.Second*40, func() { dm.Close(); }); dm.Start(); }
相關推薦
golang 實現延遲訊息原理與方法
package main; import ( "time" "errors" "fmt" ) //延遲訊息 type DelayMessage struct { //當前下標 curIndex int; //環形槽 slots [3600]map[string]
手機定位軟體實現號碼定位找人的原理與方法
隨著智慧手機的普及,越來越多的人想要定位別人的或者是好友的手機位置,那麼手機定位精確找人到底靠不靠譜呢?今天就為大家講解下手機定位軟體實現號碼定位的原理和方法。手機號碼定位,還有個學名,也就是基站定位,相信大家並不陌生,它依託於三大運營商的資料庫,以附近三個基站訊號塔為定位點
例項解釋瀑布流圖的實現原理與方法
今天博主上網搜了一下關於瀑布流圖的文章,發現實現瀑布流圖的方法大概有“通過JS排版”與“通過後臺排版”兩種。博主認為“通過JS排版”是一種更好的方法,而且網上也是普遍這麼認為的。所以博主先簡單介紹一下“通過後臺排版”的原理,然後在詳細說說“通過JS排版”的原理以及實現過程。
淺談如何通過自媒體渠道實現賺錢的途徑與方法?
自媒體 賺錢 思考 眾所周知,隨著互聯網時代的不斷發展,越來越多的網民已經意識到通過網絡能賺到錢。不過在網絡上能賺錢的項目不計其數,包括現在比較火的自媒體,那麽我們怎麽去分辨一個項目的靠譜性呢?我們需要考慮的幾個問題:1. 項目是否需要投資;2. 項目是否有風險;3. 項目的長久性;4. 項目的回
rabbitmq實現延遲訊息(附原始碼)
rabbitmq實現延遲訊息的方案 1. 使用延時佇列 單機不考慮拓展的情況下,可以使用java.util.concurrent包的DelayQueue, 但插入的物件需實現Delayed介面,並實現其getDelay方法。 優點:針對任意訊息佇列均可使用 缺
golang實現簡易的分散式系統方法
本文介紹了golang實現簡易的分散式系統方法,分享給大家,具體如下: 功能 能夠傳送/接收請求和響應 能夠連線到叢集 如果無法連線到群集(如果它是第一個節點),則可以作為主節點啟動節點 每個節點有唯一的標識 能夠在節點之間交換json資料包 接受命令列引數中的所有資訊(將來在我們系
點陣字模生成原理與方法
點陣字模生成原理與方法 字模生成原理 本設計中因為使用漢字的點陣顯示,需要提取漢字字模,因此我們首先來了解漢字點陣字模的提取方法。 漢字的點陣字模是從點陣字型檔檔案中提取出來的。例如常用的16×16點陣HZK16檔案,12×12點陣HZK12檔案等等,這些檔案包括了GB
Web GIS原理與方法
開學第三週,正是進入上課狀態,今天一整天的滿課,極度的睏倦,顯然還在適應著上課,本以為一上午的課會小憩一會,但是因為老師的講授,竟然一刻也沒有走神,感覺老師的講課方式很棒,似乎是又給我們打開了一扇窗,特此記錄。 WebGIS顯然是當今GIS發展的一大主要趨勢,WebGIS
瞭解基於視覺的缺陷檢測的原理與方法
一、KNN分類器 1.1.1最近鄰演算法 定義:計算未知樣本與所有訓練樣本的距離,並以最近鄰者的類別作為決策未知樣本類別的唯一依據。 缺陷:對噪聲資料過於敏感。 措施:將被決策樣本週邊的多個最近樣本計算在內,擴大參與決策的樣本量,以避免個別資料直接決定決策結果。 1.1.2K-最
Android實現延遲的幾種方法小結
本文例項總結了Android實現延遲的幾種方法。分享給大家供大家參考,具體如下: 一、通過Thread new Thread(){ public void run(){ sleep(***); } }.start(); 通過ProgressDialog的使用來
YAML的Java實現——JYAML基本原理與示例(1)匯出資料為YAML格式檔案
1. Overview JYAML是YAML的Java實現,YAML的全稱是YAML Ain't Markup Language,是否定遞迴定義,和LINUX的Linux Is Not UniX是一個意思。其結構之簡單,常常成為匯出或匯入配置檔案、資料結構等應用場景的常用A
YAML的Java實現——JYAML基本原理與示例(3)YAML對檔案流的處理
請您先閱讀: 1. FileOutputStream 以流的方式,將資料寫入到YAML檔案中。 /* Output data structure into a YAML file as a
YAML的Java實現——JYAML基本原理與示例(2)匯入YAML格式檔案
1. 定義好的YAML檔案testYaml.yaml --- &0 !com.sinosuperman.yaml.Person age: 24 children: &2 !com
百度雲滿速下載原理與方法
前言 今天給大家介紹一款好用的開源工具proxyee-down,之前已經測試了好多天了,挺強大,可以滿速下載百度雲裡的檔案,而且不用輸入賬號,因此不存在盜號的可能性。 github地址: 百度雲下載地址: 百度大檔案破解 1.限速與封號 使用過百度雲的朋友肯定知道,百度雲客戶端限速太厲害,我用的翼訊速度
MQ實現“延遲訊息”功能
轉載文章:轉自個人微信公眾號[架構師之路];作者:[沈劍] 一、緣起 很多時候,業務有“在一段時間之後,完成一個工作任務”的需求。 例如:滴滴打車訂單完成後,如果使用者一直不評價,48小時後會將自動評價為5星。 一般來說怎麼實現這類“48小時後自動評價為5星
kafka實現無訊息丟失與精確一次語義(exactly once)處理
在很多的流處理框架的介紹中,都會說kafka是一個可靠的資料來源,並且推薦使用Kafka當作資料來源來進行使用。這是因為與其他訊息引擎系統相比,kafka提供了可靠的資料儲存及備份機制。並且通過消費者位移這一概念,可以讓消費者在因某些原因宕機而重啟後,可以輕易得回到宕機前的位置。 但其實kafka的可靠性也
golang實現常用集合原理介紹
golang本身對常用集合的封裝還是比較少的,主要有陣列(切片)、雙向連結串列、堆等。在工作中可能用到其他常用的集合,於是我自己對常用的集合進行了封裝,並對原理做了簡單介紹,程式碼庫地址:https://github.com/chentaihan/container,程式碼都是經過測試的,歡迎下載使用,反饋
分頁技術原理與實現之分頁的意義及方法(一)
轉載自https://www.jb51.net/article/86326.htm。 什麼是分頁技術 分頁,是一種將所有資料分段展示給使用者的技術.使用者每次看到的不是全部資料,而是其中的一部分,如果在其中沒有找到自習自己想要的內容,使用者可以通過制定頁碼或是翻頁的方式轉換可見內容,
機器學習方法(四):決策樹Decision Tree原理與實現技巧
歡迎轉載,轉載請註明:本文出自Bin的專欄blog.csdn.net/xbinworld。 技術交流QQ群:433250724,歡迎對演算法、技術、應用感興趣的同學加入。 前面三篇寫了線性迴歸,lasso,和LARS的一些內容,這篇寫一下決策樹這個經典的分
《機器學習實戰》AdaBoost方法的演算法原理與程式實現
一、引言提升(boosting)方法是一種常用的統計學習方法,應用廣泛且有效,在分類問題中,它通過改變訓練樣本的權重,學習多個分類器,並將這些分類器進行線性組合,提高分類的效能。對於分類問題,給定一個訓練樣本集,比較粗糙的分類規則(弱分類器),要比精確分類規則(強分類器)容易