欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go?Ticker?周期性定時(shí)器用法及實(shí)現(xiàn)原理詳解

 更新時(shí)間:2022年08月25日 09:59:31   作者:yi個(gè)俗人  
這篇文章主要為大家介紹了Go?Ticker?周期性定時(shí)器用法及實(shí)現(xiàn)原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

定時(shí)器在Go語(yǔ)言應(yīng)用中使用非常廣泛,Go語(yǔ)言的標(biāo)準(zhǔn)庫(kù)里提供兩種類型的計(jì)時(shí)器,一種是一次性的定時(shí)器Timer,另外一種是周期性的定時(shí)器Ticker。本文主要來(lái)看一下Ticker的用法和實(shí)現(xiàn)原理,需要的朋友可以參考以下內(nèi)容,希望對(duì)大家有幫助。

Ticker

Ticker是周期性定時(shí)器,即周期性的觸發(fā)一個(gè)事件,它會(huì)以一個(gè)間隔(interval)往channel發(fā)送一個(gè)事件(當(dāng)前時(shí)間),而channel的接收者可以以固定的時(shí)間間隔從channel中讀取事件。通過(guò)Ticker本身提供的管道將事件傳遞出去。

應(yīng)用示例

package main
import (
	"fmt"
	"time"
)
func main()  {
	ticker := time.NewTicker(time.Second * 1) //創(chuàng)建一個(gè)周期性定時(shí)器
	i := 1
	for  {
		fmt.Println(i, "====>", <-ticker.C)
		if i == 5 {
			ticker.Stop() //停止定時(shí)器
			break
		}
		i++
	}
}

輸出結(jié)果:

1 ====> 2022-08-24 15:58:38.971837 +0800 CST m=+1.001366085
2 ====> 2022-08-24 15:58:39.971154 +0800 CST m=+2.000695418
3 ====> 2022-08-24 15:58:40.971633 +0800 CST m=+3.001185460
4 ====> 2022-08-24 15:58:41.97109 +0800 CST m=+4.000654126
5 ====> 2022-08-24 15:58:42.971594 +0800 CST m=+5.001169210

創(chuàng)建定時(shí)器

使用NewTicker()方法就可以創(chuàng)建一個(gè)周期性定時(shí)器,函數(shù)如下:

func NewTicker(d Duration) *Ticker

其中參數(shù)d即為定時(shí)器時(shí)間觸發(fā)的周期,為一個(gè)時(shí)間段。

停止定時(shí)器

使用定時(shí)器對(duì)外暴露的 Stop 方法就可以停掉一個(gè)周期性定時(shí)器, 函數(shù)如下:

func (t *Ticker) Stop()

該方法會(huì)停止計(jì)時(shí),停止后不會(huì)向定時(shí)器的管道中寫入事件,但管道并不會(huì)被關(guān)閉。

管道在使用完成后,生命周期結(jié)束后會(huì)自動(dòng)釋放。

實(shí)現(xiàn)原理

數(shù)據(jù)結(jié)構(gòu)

Ticker的數(shù)據(jù)結(jié)構(gòu)與Timer完全一致:

通過(guò)src/time.sleep.go:Ticker定義了Timer數(shù)據(jù)結(jié)構(gòu):

type Ticker struct {
    C <-chan Time
    r runtimeTimer
}

它提供了一個(gè)channel,在定時(shí)時(shí)間到達(dá)之前,沒(méi)有數(shù)據(jù)寫入Ticker.C會(huì)一直阻塞,直到時(shí)間到達(dá),向channel寫入系統(tǒng)時(shí)間,阻塞解除,可以從中讀取數(shù)據(jù),這就是一個(gè)事件。

我們可以理解為Ticker.C即面向Ticker用戶的,Ticker.r是面向底層的定時(shí)器實(shí)現(xiàn)。

runtimeTimer

runtimeTimer與Timer一樣,任務(wù)的載體,用于監(jiān)控定時(shí)任務(wù),每創(chuàng)建一個(gè)Timer就創(chuàng)建一個(gè)runtimeTimer變量,然后把它交給系統(tǒng)進(jìn)行監(jiān)控,我們通過(guò)設(shè)置runtimeTimer過(guò)期后的行為來(lái)達(dá)到定時(shí)的目的。

源碼包src/time/sleep.go:runtimeTimer定義了其數(shù)據(jù)結(jié)構(gòu):

type runtimeTimer struct {
    tb uintptr                          // 存儲(chǔ)當(dāng)前定時(shí)器的數(shù)組地址
    i  int                              // 存儲(chǔ)當(dāng)前定時(shí)器的數(shù)組下標(biāo)
    when   int64                        // 當(dāng)前定時(shí)器觸發(fā)時(shí)間
    period int64                        // 當(dāng)前定時(shí)器周期觸發(fā)間隔
    f      func(interface{}, uintptr)   // 定時(shí)器觸發(fā)時(shí)執(zhí)行的函數(shù)
    arg    interface{}                  // 定時(shí)器觸發(fā)時(shí)執(zhí)行函數(shù)傳遞的參數(shù)一
    seq    uintptr                      // 定時(shí)器觸發(fā)時(shí)執(zhí)行函數(shù)傳遞的參數(shù)二(該參數(shù)只在網(wǎng)絡(luò)收發(fā)場(chǎng)景下使用)
}

創(chuàng)建Ticker

func NewTicker(d Duration) *Ticker {
    if d <= 0 {
        panic(errors.New("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{
        C: c,
        r: runtimeTimer{
            when:   when(d),
            period: int64(d), // Ticker跟Timer的重要區(qū)就是提供了period這個(gè)參數(shù),據(jù)此決定timer是一次性的,還是周期性的
            f:      sendTime,
            arg:    c,
        },
    }
    startTimer(&t.r)
    return t
}

NewTicker()構(gòu)造了一個(gè)Ticker,然后把Ticker.r通過(guò)startTimer()交給系統(tǒng)協(xié)程維護(hù)。

其中period為事件觸發(fā)的周期。

停止Ticker

停止Ticker,只是把Ticker從系統(tǒng)協(xié)程中移除。

func (t *Ticker) Stop() {
    stopTimer(&t.r)
}

stopTicker()即通知系統(tǒng)協(xié)程把該Ticker移除,即不再監(jiān)控。系統(tǒng)協(xié)程只是移除Ticker并不會(huì)關(guān)閉管道,以避免用戶協(xié)程讀取錯(cuò)誤。

注意:

Ticker在使用完后務(wù)必要釋放,否則會(huì)產(chǎn)生資源泄露,進(jìn)而會(huì)持續(xù)消耗CPU資源,最后會(huì)把CPU耗盡。

ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()

Ticker 與 Timer 區(qū)別

  • Ticker —— 重復(fù)性執(zhí)行任務(wù)非常有用呢
  • Timer —— 用于執(zhí)行一次性任務(wù)

小結(jié)

Ticker相關(guān)內(nèi)容總結(jié)如下:

  • 使用time.NewTicker()來(lái)創(chuàng)建一個(gè)定時(shí)器;
  • 使用Stop()來(lái)停止一個(gè)定時(shí)器;
  • 定時(shí)器使用完畢要釋放,否則會(huì)產(chǎn)生資源泄露;

如果需要了解Timer,可以看這篇文章 http://www.dbjr.com.cn/article/260598.htm

以上就是Go Ticker 周期性定時(shí)器用法及實(shí)現(xiàn)原理詳解的詳細(xì)內(nèi)容,更多關(guān)于Go Ticker周期性定時(shí)器的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Go語(yǔ)言如何使用golang-jwt/jwt/v4進(jìn)行JWT鑒權(quán)詳解

    Go語(yǔ)言如何使用golang-jwt/jwt/v4進(jìn)行JWT鑒權(quán)詳解

    最近項(xiàng)目中需要用到鑒權(quán)機(jī)制,golang中jwt可以用,這篇文章主要給大家介紹了關(guān)于Go語(yǔ)言如何使用golang-jwt/jwt/v4進(jìn)行JWT鑒權(quán)的相關(guān)資料,需要的朋友可以參考下
    2022-09-09
  • goland使用go mod模式的步驟詳解

    goland使用go mod模式的步驟詳解

    這篇文章主要介紹了goland使用go mod模式的步驟詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • Go語(yǔ)言map不支持并發(fā)寫操作的原因

    Go語(yǔ)言map不支持并發(fā)寫操作的原因

    Go語(yǔ)言為什么不支持并發(fā)讀寫map?,Go官方的說(shuō)法是在多數(shù)情況下map只存在并發(fā)讀操作,如果原生支持并發(fā)讀寫,即降低了并發(fā)讀操作的性能,在使用?map?時(shí),要特別注意是否存在對(duì)?map?的并發(fā)寫操作,如果存在,要結(jié)合?sync?包的互斥鎖一起使用,
    2024-01-01
  • Go語(yǔ)言之Goroutine與信道異常處理

    Go語(yǔ)言之Goroutine與信道異常處理

    這篇文章主要給大家介紹得是Go語(yǔ)言Goroutine與信道異常處理,Goroutine 之間通信是通過(guò) channel 通信的,想詳細(xì)了解得小伙伴跟小編一起來(lái)學(xué)習(xí)下面文章內(nèi)容吧
    2021-10-10
  • golang中set數(shù)據(jù)結(jié)構(gòu)的使用示例

    golang中set數(shù)據(jù)結(jié)構(gòu)的使用示例

    本文主要介紹了golang中set數(shù)據(jù)結(jié)構(gòu)的使用示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • 重學(xué)Go語(yǔ)言之如何開(kāi)發(fā)RPC應(yīng)用

    重學(xué)Go語(yǔ)言之如何開(kāi)發(fā)RPC應(yīng)用

    這篇文章主要為大家詳細(xì)介紹了在Go語(yǔ)言中如何構(gòu)建RPC應(yīng)用,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-09-09
  • Go語(yǔ)言學(xué)習(xí)之goroutine詳解

    Go語(yǔ)言學(xué)習(xí)之goroutine詳解

    Goroutine是建立在線程之上的輕量級(jí)的抽象。它允許我們以非常低的代價(jià)在同一個(gè)地址空間中并行地執(zhí)行多個(gè)函數(shù)或者方法,這篇文章主要介紹了Go語(yǔ)言學(xué)習(xí)之goroutine的相關(guān)知識(shí),需要的朋友可以參考下
    2020-02-02
  • Go高級(jí)特性探究之穩(wěn)定排序詳解

    Go高級(jí)特性探究之穩(wěn)定排序詳解

    Go 語(yǔ)言提供了 sort 包,其中最常用的一種是 sort.Slice() 函數(shù),本篇文章將為大家介紹如何使用 sort.SliceStable() 對(duì)結(jié)構(gòu)體數(shù)組的某個(gè)字段進(jìn)行穩(wěn)定排序,感興趣的可以了解一下
    2023-06-06
  • golang連接MongoDB數(shù)據(jù)庫(kù)及數(shù)據(jù)庫(kù)操作指南

    golang連接MongoDB數(shù)據(jù)庫(kù)及數(shù)據(jù)庫(kù)操作指南

    MongoDB是Nosql中常用的一種數(shù)據(jù)庫(kù),下面這篇文章主要給大家介紹了關(guān)于golang連接MongoDB數(shù)據(jù)庫(kù)及數(shù)據(jù)庫(kù)操作的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-09-09
  • 一文詳細(xì)介紹golang中.()類型斷言的使用方法

    一文詳細(xì)介紹golang中.()類型斷言的使用方法

    Golang是一門非常流行的編程語(yǔ)言,在很多領(lǐng)域都有著廣泛的應(yīng)用,在開(kāi)發(fā)過(guò)程中,很多時(shí)候我們需要將函數(shù)作為參數(shù)傳遞給其他函數(shù),這時(shí)候就需要用到golang中的.()用法,本文將詳細(xì)介紹golang中.()的使用方法,需要的朋友可以參考下
    2023-08-08

最新評(píng)論