go語言定時操作 go語言臨時指針

golang之context詳解

為什么需要context

成都創(chuàng)新互聯(lián)是一家專業(yè)提供瀘水企業(yè)網(wǎng)站建設(shè),專注與網(wǎng)站建設(shè)、成都網(wǎng)站制作、HTML5建站、小程序制作等業(yè)務。10年已為瀘水眾多企業(yè)、政府機構(gòu)等服務。創(chuàng)新互聯(lián)專業(yè)網(wǎng)站建設(shè)公司優(yōu)惠進行中。

在go服務器中,對于每個請求的request都是在單獨的goroutine中進行的,處理一個request也可能設(shè)計多個goroutine之間的交互, 使用context可以使開發(fā)者方便的在這些goroutine里傳遞request相關(guān)的數(shù)據(jù)、取消goroutine的signal或截止日期

在并發(fā)程序中,由于超時、取消操作或者一些異常情況,往往需要進行搶占操作或者中斷后續(xù)操作。熟悉channel的朋友應該都見過使用done channel來處理此類問題。比如以下這個例子:

上述例子中定義了一個buffer為0的channel done, 子協(xié)程運行著定時任務。如果主協(xié)程需要在某個時刻發(fā)送消息通知子協(xié)程中斷任務退出,那么就可以讓子協(xié)程監(jiān)聽這個done channel,一旦主協(xié)程關(guān)閉done channel,那么子協(xié)程就可以推出了,這樣就實現(xiàn)了主協(xié)程通知子協(xié)程的需求。這很好,但是這也是有限的。

如果我們可以在簡單的通知上附加傳遞額外的信息來控制取消:為什么取消,或者有一個它必須要完成的最終期限,更或者有多個取消選項,我們需要根據(jù)額外的信息來判斷選擇執(zhí)行哪個取消選項。

考慮下面這種情況:假如主協(xié)程中有多個任務1, 2, …m,主協(xié)程對這些任務有超時控制;而其中任務1又有多個子任務1, 2, …n,任務1對這些子任務也有自己的超時控制,那么這些子任務既要感知主協(xié)程的取消信號,也需要感知任務1的取消信號。

如果還是使用done channel的用法,我們需要定義兩個done channel,子任務們需要同時監(jiān)聽這兩個done channel。嗯,這樣其實好像也還行哈。但是如果層級更深,如果這些子任務還有子任務,那么使用done channel的方式將會變得非常繁瑣且混亂。

我們需要一種優(yōu)雅的方案來實現(xiàn)這樣一種機制:

上層任務取消后,所有的下層任務都會被取消;中間某一層的任務取消后,只會將當前任務的下層任務取消,而不會影響上層的任務以及同級任務。

這個時候context就派上用場了。我們首先看看context的結(jié)構(gòu)設(shè)計和實現(xiàn)原理。

context接口

先看Context接口結(jié)構(gòu),看起來非常簡單。

}

Context接口包含四個方法:

Deadline返回綁定當前context的任務被取消的截止時間;如果沒有設(shè)定期限,將返回ok == false。

Done 當綁定當前context的任務被取消時,將返回一個關(guān)閉的channel;如果當前context不會被取消,將返回nil。

Err 如果Done返回的channel沒有關(guān)閉,將返回nil;如果Done返回的channel已經(jīng)關(guān)閉,將返回非空的值表示任務結(jié)束的原因。如果是context被取消,Err將返回Canceled;如果是context超時,Err將返回DeadlineExceeded。

Value 返回context存儲的鍵值對中當前key對應的值,如果沒有對應的key,則返回nil。

可以看到Done方法返回的channel正是用來傳遞結(jié)束信號以搶占并中斷當前任務;Deadline方法指示一段時間后當前goroutine是否會被取消;以及一個Err方法,來解釋goroutine被取消的原因;而Value則用于獲取特定于當前任務樹的額外信息。而context所包含的額外信息鍵值對是如何存儲的呢?其實可以想象一顆樹,樹的每個節(jié)點可能攜帶一組鍵值對,如果當前節(jié)點上無法找到key所對應的值,就會向上去父節(jié)點里找,直到根節(jié)點。

emptyCtx

emptyCtx是一個int類型的變量,但實現(xiàn)了context的接口。emptyCtx沒有超時時間,不能取消,也不能存儲任何額外信息,所以emptyCtx用來作為context樹的根節(jié)點。

Background和TODO只是用于不同場景下: Background通常被用于主函數(shù)、初始化以及測試中,作為一個頂層的context,也就是說一般我們創(chuàng)建的context都是基于Background;而TODO是在不確定使用什么context的時候才會使用。

用法 :

如何在 Golang 定時任務中判斷函數(shù)是否執(zhí)行完成

一般都是通過日志打印

譬如run方法里面加入以下

log.info("定時器啟動,時間:"+new Date())

try{

}catch(){

log.error("出現(xiàn)異常")

return;

}

log.info("定時器結(jié)束,時間:"+new Date())

當日志打印有結(jié)束語句就證明跑完了

golang 定時器,啟動的時候執(zhí)行一次,以后每天晚上12點執(zhí)行,怎么實現(xiàn)

func?startTimer(f?func())?{

go?func()?{

for?{

f()

now?:=?time.Now()

//?計算下一個零點

next?:=?now.Add(time.Hour?*?24)

next?=?time.Date(next.Year(),?next.Month(),?next.Day(),?0,?0,?0,?0,?next.Location())

t?:=?time.NewTimer(next.Sub(now))

-t.C

}

}()

}

Go語言基于Etcd實現(xiàn)的定時任務

利用 Etcd 的Lease租約特性來實現(xiàn)定時功能,同時通過Watch機制來實現(xiàn)多節(jié)點情況下只有一個節(jié)點執(zhí)行該任務。通過定時任務庫 Cron 的時間字符串解析器Parser來解析任務執(zhí)行時間。

Etcd

Cron

源碼鏈接

Golang-基于TimeingWheel定時器

在linux下實現(xiàn)定時器主要有如下方式

在這當中 基于時間輪方式實現(xiàn)的定時器 時間復雜度最小,效率最高,然而我們可以通過 優(yōu)先隊列 實現(xiàn)時間輪定時器。

優(yōu)先隊列的實現(xiàn)可以使用最大堆和最小堆,因此在隊列中所有的數(shù)據(jù)都可以定義排序規(guī)則自動排序。我們直接通過隊列中 pop 函數(shù)獲取數(shù)據(jù),就是我們按照自定義排序規(guī)則想要的數(shù)據(jù)。

在 Golang 中實現(xiàn)一個優(yōu)先隊列異常簡單,在 container/head 包中已經(jīng)幫我們封裝了,實現(xiàn)的細節(jié),我們只需要實現(xiàn)特定的接口就可以。

下面是官方提供的例子

因為優(yōu)先隊列底層數(shù)據(jù)結(jié)構(gòu)是由二叉樹構(gòu)建的,所以我們可以通過數(shù)組來保存二叉樹上的每一個節(jié)點。

改數(shù)組需要實現(xiàn) Go 預先定義的接口 Len , Less , Swap , Push , Pop 和 update 。

timerType結(jié)構(gòu)是定時任務抽象結(jié)構(gòu)

首先的 start 函數(shù),當創(chuàng)建一個 TimeingWheel 時,通過一個 goroutine 來執(zhí)行 start ,在start中for循環(huán)和select來監(jiān)控不同的channel的狀態(tài)

通過for循環(huán)從隊列中取數(shù)據(jù),直到該隊列為空或者是遇見第一個當前時間比任務開始時間大的任務, append 到 expired 中。因為優(yōu)先隊列中是根據(jù) expiration 來排序的,

所以當取到第一個定時任務未到的任務時,表示該定時任務以后的任務都未到時間。

當 getExpired 函數(shù)取出隊列中要執(zhí)行的任務時,當有的定時任務需要不斷執(zhí)行,所以就需要判斷是否該定時任務需要重新放回優(yōu)先隊列中。 isRepeat 是通過判斷任務中 interval 是否大于 0 判斷,

如果大于0 則,表示永久就生效。

防止外部濫用,阻塞定時器協(xié)程,框架又一次封裝了timer這個包,名為 timer_wapper 這個包,它提供了兩種調(diào)用方式。

參數(shù)和上面的參數(shù)一樣,只是在第三個參數(shù)中使用了任務池,將定時任務放入了任務池中。定時任務的本身執(zhí)行就是一個 put 操作。

至于put以后,那就是 workers 這個包管理的了。在 worker 包中, 也就是維護了一個任務池,任務池中的任務會有序的執(zhí)行,方便管理。

分享題目:go語言定時操作 go語言臨時指針
當前路徑:http://www.muchs.cn/article16/doocigg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站排名、網(wǎng)站制作、品牌網(wǎng)站設(shè)計、靜態(tài)網(wǎng)站小程序開發(fā)網(wǎng)站設(shè)計

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站托管運營