go語言-time.Ticker(定時任務實現)

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,以避免從該通道的讀取不正確的成功。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章