Go語言 之time.Ticker
Go語言 之time.Ticke
參考URL: Code.dev.xdja.com/diffusion/
Golang time.Timer and time.Ticker
參考URL: https://www.jianshu.com/p/2b4686b8de4a
time.Timer
首先我們看Timer的結構定義:
type Timer struct {
C <-chan Time
r runtimeTimer
}
其中有一個C的只讀channel,還有一個runtimeTimer類型的結構體,再看一下這個結構的具體結構:
type runtimeTimer struct {
tb uintptr
i int
when int64
period int64
f func(interface{}, uintptr) // NOTE: must not be closure
arg interface{}
seq uintptr
}
在使用定時timer的時候都是通過 NewTimer 或 AfterFunc 函數來獲取。
func NewTimer(d Duration) *Timer {
c := make(chan Time, 1)
t := &Timer{
C: c,
r: runtimeTimer{
when: when(d), //表示達到時間段d時候調用f
f: sendTime, // f表示一個函數調用,這裏的sendTime表示d時間到達時向Timer.C發送當前的時間
arg: c, // arg表示在調用f的時候把參數arg傳遞給f,c就是用來接受sendTime發送時間的
},
}
startTimer(&t.r)
return t
}
定時器的具體實現邏輯,都在 runtime 中的 time.go 中,它的實現,沒有采用經典 Unix 間隔定時器 setitimer 系統調用,也沒有 採用 POSIX間隔式定時器(相關係統調用:timer_create、timer_settime 和 timer_delete),而是通過四叉樹堆(heep)實現的(runtimeTimer 結構中的i字段,表示在堆中的索引)。通過構建一個最小堆,保證最快拿到到期了的定時器執行。定時器的執行,在專門的 goroutine 中進行的:go timerproc()。有興趣的同學,可以閱讀 runtime/time.go 的。
使用舉例
package main
import (
"fmt"
"time"
)
func main() {
//創建定時器,每隔1秒後,定時器就會給channel發送一個事件(當前時間)
ticker := time.NewTicker(time.Second * 1)
i := 0
go func() {
for { //循環
<-ticker.C
i++
fmt.Println("i = ", i)
if i == 5 {
ticker.Stop() //停止定時器
}
}
}() //別忘了()
//死循環,特地不讓main goroutine結束
for {
}
}
Ticker是一個週期觸發定時的計時器,它會按照一個時間間隔往channel發送系統當前時間,而channel的接收者可以以固定的時間間隔從channel中讀取事件。
相關函數:
NewTicker()返回一個新的Ticker,該Ticker包含一個通道字段,並會每隔時間段d就向該通道發送當時的時間。它會調整時間間隔或者丟棄tick信息以適應反應慢的接收者。如果d<=0會panic。關閉該Ticker可以釋放相關資源。
Stop()關閉一個Ticker。在關閉後,將不會發送更多的tick信息。Stop不會關閉通道t.C,以避免從該通道的讀取不正確的成功。