Go進階之定時器Ticker的實現(xiàn)示例
Ticker是周期性定時器.即周期性的觸發(fā)一個事件.通過Ticker本身提供的管道將事件
傳遞出去.
Ticker數(shù)據(jù)結(jié)構(gòu):
源碼位置:src/time/tick.go
type Ticker struct {
C <-chan Time // The channel on which the ticks are delivered.
initTicker bool
}
Ticker對外僅暴露了一個channel.當指定時間到來時就往該channel中寫入系統(tǒng)時
間.即一個事件.
1.簡單定時任務:
func main() {
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
for range ticker.C {
log.Println("tick")
}
}
執(zhí)行結(jié)果:

定時聚合任務:
示例:
func TickerLaunch() {
//5分鐘執(zhí)行一次.
ticker := time.NewTicker(5 * time.Minute)
defer ticker.Stop()
maxPassenger := 30
passengers := make([]string, 0, maxPassenger)
for {
passenger := GetNewPassenger()
if passenger != "" {
passengers = append(passengers, passenger)
} else {
time.Sleep(1 * time.Second)
}
select {
case <-ticker.C:
Launch(passengers)
passengers = []string{}
default:
if len(passengers) >= maxPassenger {
Launch(passengers)
passengers = []string{}
}
}
}
}
func Launch(passengers []string) {
for i := range passengers {
fmt.Println(passengers[i], "發(fā)車了")
}
}
func GetNewPassenger() string {
return "乘客"
}
2.Ticker對外接口:
1)創(chuàng)建定時器:
源碼位置:src/time/tick.go
func NewTicker(d Duration) *Ticker {
if d <= 0 {
panic("non-positive interval for NewTicker")
}
// Give the channel a 1-element time buffer.
// If the client falls behind while reading, we drop ticks
// on the floor until the client catches up.
c := make(chan Time, 1)
t := (*Ticker)(unsafe.Pointer(newTimer(when(d), int64(d), sendTime, c, syncTimer(c))))
t.C = c
return t
}

2).停止定時器:
源碼位置:src/time/tick.go
// Stop turns off a ticker. After Stop, no more ticks will be sent.
// Stop does not close the channel, to prevent a concurrent goroutine
// reading from the channel from seeing an erroneous "tick".
func (t *Ticker) Stop() {
if !t.initTicker {
// This is misuse, and the same for time.Timer would panic,
// but this didn't always panic, and we keep it not panicking
// to avoid breaking old programs. See issue 21874.
return
}
stopTimer((*Timer)(unsafe.Pointer(t)))
}

流程圖:

總流程圖:

3.簡單接口:
在有些場景下.啟動一個定時器后.該定時器永遠不會停止.比如定時輪詢?nèi)蝿?此時可
以使用一個簡單的Tick函數(shù)來獲取定時器的管道.函數(shù)如下:
源碼位置:src/runtime/tick.go
func Tick(d Duration) <-chan Time {
if d <= 0 {
return nil
}
return NewTicker(d).C
}
從源碼可以看出其實是創(chuàng)建了一個Ticker.然后只返回了管道.并沒有返回ticker.所以
沒有辦法停止.
4.錯誤示例:
當Ticker用于for循環(huán)時.很容易出現(xiàn)意想不到的資源泄漏問題.
示例:
func WrongTicker() {
for {
select {
case <-time.Tick(time.Second):
log.Printf("resource leak!")
}
}
}
上面的代碼.select每次檢測case語句都會創(chuàng)建一個定時器.for循環(huán)又會不斷的執(zhí)行
select語句.系統(tǒng)里會有越來越多的定時器不斷地消耗CPU資源.最終CPU資源被耗
到此這篇關于Go進階之定時器Ticker的實現(xiàn)示例的文章就介紹到這了,更多相關Go 定時器Ticker內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
golang 實現(xiàn)每隔幾分鐘執(zhí)行一個函數(shù)
這篇文章主要介紹了golang 實現(xiàn)每隔幾分鐘執(zhí)行一個函數(shù),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12

