中文字幕日韩精品一区二区免费_精品一区二区三区国产精品无卡在_国精品无码专区一区二区三区_国产αv三级中文在线

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

golang之context詳解

為什么需要context

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

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

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

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

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

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

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

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

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

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

context接口

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

}

Context接口包含四個方法:

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

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

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

Value 返回context存儲的鍵值對中當(dāng)前key對應(yīng)的值,如果沒有對應(yīng)的key,則返回nil。

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

emptyCtx

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

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

用法 :

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

一般都是通過日志打印

譬如run方法里面加入以下

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

try{

}catch(){

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

return;

}

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

當(dāng)日志打印有結(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)的定時任務(wù)

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

Etcd

Cron

源碼鏈接

Golang-基于TimeingWheel定時器

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

在這當(dāng)中 基于時間輪方式實現(xiàn)的定時器 時間復(fù)雜度最小,效率最高,然而我們可以通過 優(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 預(yù)先定義的接口 Len , Less , Swap , Push , Pop 和 update 。

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

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

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

所以當(dāng)取到第一個定時任務(wù)未到的任務(wù)時,表示該定時任務(wù)以后的任務(wù)都未到時間。

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

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

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

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

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

分享題目:go語言定時操作 go語言臨時指針
當(dāng)前路徑:http://m.rwnh.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)站托管運營
太谷县| 沂水县| 丹寨县| 竹溪县| 手游| 宿州市| 贺州市| 太仓市| 福贡县| 闵行区| 丽江市| 三江| 南安市| 吉林省| 额敏县| 阜城县| 南召县| 红原县| 满洲里市| 伊春市| 高州市| 隆子县| 健康| 峡江县| 达拉特旗| 尚志市| 淮南市| 六枝特区| 铜山县| 巢湖市| 离岛区| 宁化县| 德江县| 蒙城县| 襄城县| 山阳县| 忻城县| 师宗县| 通榆县| 和林格尔县| 卫辉市|