Golang中定時器的陷阱詳解

2022-09-24 14:51:18 字數 1637 閱讀 6063

前言

在業務中,我們經常需要基於定時任務來觸發來實現各種功能。比如ttl會話管理、鎖、定時任務(鬧鐘)或更複雜的狀態切換等等。百納網主要給大家介紹了關於golang定時器陷阱的相關內容,所謂陷阱,就是它不是你認為的那樣,這種認知誤差可能讓你的軟體留下隱藏bug。剛好timer就有3個陷阱,我們會講

1)reset的陷阱和

2)通道的陷阱,

3)stop的陷阱與reset的陷阱類似,自己探索吧。

下面話不多說了,來一起看看詳細的介紹吧

reset的陷阱在哪

timer.reset()函式的返回值是bool型別,我們看乙個問題三連:

成功:一段時間之後定時www.cppcns.com器超時,收到超時事件。

失敗:成功的反面,我們收不到那個事件。對於失敗,我們應當做些什麼,確保我們的定時器發揮作用。

reset的返回值是不是這個意思?

通過檢視文件和實現,timer.reset()的返回值並不符合我們的預期,這就是誤差。它的返回值不代表重設定時器成功或失敗,而是在表達定時器在重設前的狀態:

所以,當reset返回false時,我們並不能認為一段時間之後,超時不會到來,實際上可能會到來,定時器已經生效了。

跳過陷阱,再遇陷阱

如何跳過前面的陷阱,讓reset符合我們的預期功能呢?直接忽視reset的返回值好了,它不能幫助你達到預期的效果。

真正的陷阱是timer的通道,它和我們預期的成功、失敗密切相關。我們所期望的定時器設定失敗,通常只和通道有關:設定定時器前,定時器的通道timer.c中是否已經有資料。

接下來解釋為何失敗只與通道中是否存在超時事件有關。

定時器的快取通道大小只為1,無法多存放超時事件,看原始碼。

// newtimer creates a new timer that will send

// the cuwww.cppcns.comrrent time on its channel after at least duration d.

func newtimer(d duration) *timer ,

} starttimer(&t.r)

return t

}定時器建立後是單獨執行的,超時後會向通道寫入資料,你從通道中把資料讀走。當前一次的超時資料沒有被讀取,而設定了新的定時器,然後去通道讀資料,結果讀到的是上次超時的超時事件,看似成功,實則失敗,完全掉入陷阱。

跨越陷阱,確保成功

如果確保timer.reset()成功,得到我們想要的結果?timer.reset()前清空通道。

當業務場景簡單時,沒有必要主動清空通道。比如,處理流程是:設定1次定時器,處理一次定時器,中間無中斷,下次reset前,通道必然是空的。

當業務場景複雜時,不確定通道是否為空,那就主動清除。

if len(timer.c) > 0 else

// 停止timer

tm.stop()

if !tm.reset(time.second) else

// timer超時

for else

fmt.printf("reset後通道中事件的數量:%d\n", len(tm2.c))

select {

case t := 0 {

總結本文標題: golang中定時器的陷阱詳解

本文位址:

golang中的定時器

type timer struct乙個定時器,代表未來的乙個單一事件,你可以告訴timer你要等待多長時間,它提供乙個channel,在將來的那個時間channel提供了乙個時間值 time.newtimer時間到了,只響應一次 func main time.after 2 time.second ...

golang定時器實現

golang定時器,需求是能夠在指定時間後停止。或某種條件出發停止。好,下面上貨。package main import context fmt sync time func main func stoptheworld func goclock for func goclock2 執行結果 123...

golang定時器和超時的使用詳解

我就廢話不多說了,大家還是直接看 吧 func main func senddatato a chan string 在一定時間內接收不到a的資料則超時 func getachan timeout time.duration,a chan string 補充 golang的定時器newtimer n...