最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

golang定時器Timer的用法和實(shí)現(xiàn)原理解析

 更新時間:2023年04月12日 16:31:43   作者:我是一只魚吖  
這篇文章主要介紹了golang定時器Ticker,本文主要來看一下Timer的用法和實(shí)現(xiàn)原理,需要的朋友可以參考以下內(nèi)容

一文搞懂golang定時器Timer的用法和實(shí)現(xiàn)原理

前言

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

Timer

Timer是一種單一事件的定時器,即經(jīng)過指定的時間后觸發(fā)一個事件,因?yàn)?code>Timer只執(zhí)行一次就結(jié)束,所以稱為單一事件,這個事件通過其本身提供的channel進(jìn)行通知觸發(fā)。

timer結(jié)構(gòu)體

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

// Timer代表一次定時,時間到達(dá)后僅執(zhí)行一個事件。
type Timer struct {
    C <-chan Time
    r runtimeTimer
}

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

創(chuàng)建定時器

func NewTimer(d Duration) *Timer

通過上面方法指定一個事件即可創(chuàng)建一個Timer,Timer一經(jīng)創(chuàng)建便開始計時,不需要額外的啟動命令。

示例:

func main()  {
	timer := time.NewTimer(time.Second * 5) //設(shè)置超時時間5s

	<- timer.C
	fmt.Println("Time out!")
}

停止定時器

Timer創(chuàng)建后可以隨時停止,停止計時器的方法如下:

func (t *Timer) Stop() bool

其返回值代表定時器有沒有超時:

  • true:定時器超時前停止,后續(xù)不會再有事件發(fā)送。
  • false:定時器超時后停止。

示例:

func main()  {
	timer := time.NewTimer(time.Second * 5) //設(shè)置超時時間5s
    timer.Stop()
}

重置定時器

已經(jīng)過期的定時器或者已停止的定時器,可以通過重置動作重新激活,方法如下:

func (t *Timer) Reset(d Duration) bool

重置的動作本質(zhì)上是先停掉定時器,再啟動,其返回值也即是停掉計時器的返回值。

func main()  {
	timer := time.NewTimer(time.Second * 5)

	<- timer.C
	fmt.Println("Time out!")

	timer.Stop() 
	timer.Reset(time.Second*3)  // 重置定時器
}

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

每個Go應(yīng)用程序都有一個協(xié)程專門負(fù)責(zé)管理所有的Timer,這個協(xié)程負(fù)責(zé)監(jiān)控Timer是否過期,過期后執(zhí)行一個預(yù)定義的動作,這個動作對于Timer而言就是發(fā)送當(dāng)前時間到管道中。

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

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

Timer只有兩個成員:

  • C:channel,上層應(yīng)用根據(jù)此管道接收事件;
  • r:runtimeTimer定時器,該定時器即系統(tǒng)管理的定時器,上層應(yīng)用不可見。

runtimeTimer

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

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

type runtimeTimer struct {
    tb uintptr                          // 存儲當(dāng)前定時器的數(shù)組地址
    i  int                              // 存儲當(dāng)前定時器的數(shù)組下標(biāo)

    when   int64                        // 當(dāng)前定時器觸發(fā)時間
    period int64                        // 當(dāng)前定時器周期觸發(fā)間隔
    f      func(interface{}, uintptr)   // 定時器觸發(fā)時執(zhí)行的函數(shù)
    arg    interface{}                  // 定時器觸發(fā)時執(zhí)行函數(shù)傳遞的參數(shù)一
    seq    uintptr                      // 定時器觸發(fā)時執(zhí)行函數(shù)傳遞的參數(shù)二(該參數(shù)只在網(wǎng)絡(luò)收發(fā)場景下使用)
}

創(chuàng)建Timer

源碼實(shí)現(xiàn):

func NewTimer(d Duration) *Timer {
    c := make(chan Time, 1)  // 創(chuàng)建一個管道
    t := &Timer{ // 構(gòu)造Timer數(shù)據(jù)結(jié)構(gòu)
        C: c,               // 新創(chuàng)建的管道
        r: runtimeTimer{
            when: when(d),  // 觸發(fā)時間
            f:    sendTime, // 觸發(fā)后執(zhí)行函數(shù)sendTime
            arg:  c,        // 觸發(fā)后執(zhí)行函數(shù)sendTime時附帶的參數(shù)
        },
    }
    startTimer(&t.r) // 此處啟動定時器,只是把runtimeTimer放到系統(tǒng)協(xié)程的堆中,由系統(tǒng)協(xié)程維護(hù)
    return t
}
  • NewTimer()只是構(gòu)造了一個Timer,然后把Timer.r通過startTimer()交給系統(tǒng)協(xié)程維護(hù)。
  • C 是一個帶1個容量的chan,這樣做有什么好處呢,原因是chan 無緩沖發(fā)送數(shù)據(jù)就會阻塞,阻塞系統(tǒng)協(xié)程,這顯然是不行的。
  • 回調(diào)函數(shù)設(shè)置為sendTime,執(zhí)行參數(shù)為channel,sendTime就是到點(diǎn)往C 里面發(fā)送當(dāng)前時間的函數(shù)

sendTime實(shí)現(xiàn):

//c interface{} 就是NewTimer 賦值的參數(shù),就是channel
func sendTime(c interface{}, seq uintptr) {
    select {
    case c.(chan Time) <- Now(): //寫不進(jìn)去的話,C 已滿,走default 分支
    default:
    }
}

停止Timer

停止Timer,就是把Timer從系統(tǒng)協(xié)程中移除。函數(shù)主要實(shí)現(xiàn)如下:

func (t *Timer) Stop() bool {
    return stopTimer(&t.r)
}

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

重置Timer

重置Timer時會先把timer從系統(tǒng)協(xié)程中刪除,修改新的時間后重新添加到系統(tǒng)協(xié)程中。

func (t *Timer) Reset(d Duration) bool {
    w := when(d)
    active := stopTimer(&t.r)
    t.r.when = w
    startTimer(&t.r)
    return active
}

補(bǔ)充:golang定時器Ticker

time包下有一個Ticker結(jié)構(gòu)體

// Ticker保管一個通道,并每隔一段時間向其傳遞"tick"。
type Ticker struct {
	C <-chan Time // 周期性傳遞時間信息的通道.
	r runtimeTimer
}
func NewTicker(d Duration) *Ticker{}

NewTicker返回一個新的Ticker,該Ticker包含一個通道字段,并會每隔時間段d,就向該通道發(fā)送當(dāng)時的時間。它會調(diào)整時間間隔或者丟棄tick信息以適應(yīng)反應(yīng)慢的接收者。如果d<=0會panic。關(guān)閉該Ticker可以釋放相關(guān)資源。

func (t *Ticker) Stop()

Stop關(guān)閉一個Ticker。在關(guān)閉后,將不會發(fā)送更多的tick信息。Stop不會關(guān)閉通道t.C,以避免從該通道的讀取不正確的成功。

例子

package main

import (
	"fmt"
	"time"
)

func main() {
	t := time.NewTicker(5 * time.Second) //創(chuàng)建定時器
	defer t.Stop()
    
	go sync(t)
	select {

	}
}

func sync(t *time.Ticker) {
	for {
		// 每5秒中從chan t.C 中讀取一次
		<-t.C
		fmt.Println("執(zhí)行數(shù)據(jù)備份任務(wù):", time.Now().Format("2006-01-02 15:04:05"))
	}
}

到此這篇關(guān)于golang定時器Timer的用法和實(shí)現(xiàn)原理解析的文章就介紹到這了,更多相關(guān)golang定時器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Golang中的變量學(xué)習(xí)小結(jié)

    Golang中的變量學(xué)習(xí)小結(jié)

    本文主要帶大家學(xué)習(xí)了Golang里面的四大類型的變量,十分的詳細(xì),有需要的小伙伴可以參考下
    2018-10-10
  • 關(guān)于go語言編碼需要放到src 文件夾下的問題

    關(guān)于go語言編碼需要放到src 文件夾下的問題

    這篇文章主要介紹了go語言編碼需要放到src 文件夾下的相關(guān)知識,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-10-10
  • Go語言錯誤處理異常捕獲+異常拋出

    Go語言錯誤處理異常捕獲+異常拋出

    這篇文章主要介紹了Go語言錯誤處理異常捕獲和異常拋出,Go語言的作者認(rèn)為java等語言的錯誤處理底層實(shí)現(xiàn)較為復(fù)雜,就實(shí)現(xiàn)了函數(shù)可以返回錯誤類型以及簡單的異常捕獲,雖然簡單但是也非常精妙,大大的提高了運(yùn)行效率,下文需要的朋友可以參考一下
    2022-02-02
  • Go語言中iota的具體使用

    Go語言中iota的具體使用

    Go語言中,iota是一個用于生成一系列相關(guān)常量值的常量生成器,常應(yīng)用于枚舉、位操作等場景,廣泛用于定義HTTP狀態(tài)碼、權(quán)限控制等,本文就來介紹一下iota的具體使用,感興趣的可以了解一下
    2024-11-11
  • Go語言遞歸函數(shù)的具體實(shí)現(xiàn)

    Go語言遞歸函數(shù)的具體實(shí)現(xiàn)

    本文主要介紹了Go語言遞歸函數(shù)的具體實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • GOLang單元測試用法詳解

    GOLang單元測試用法詳解

    Go語言中自帶有一個輕量級的測試框架testing和自帶的go test命令來實(shí)現(xiàn)單元測試和性能測試。本文將通過示例詳細(xì)聊聊Go語言單元測試的原理與使用,需要的可以參考一下
    2022-12-12
  • Golang中switch語句和select語句的用法教程

    Golang中switch語句和select語句的用法教程

    這篇文章主要給大家介紹了關(guān)于Golang中switch和select的用法教程,文中通過示例代碼將switch語句與select語句的使用方法介紹的非常詳細(xì),對大家具有一定的參考學(xué)習(xí)價值,需要的朋友們下面跟著小編一起來學(xué)習(xí)學(xué)習(xí)吧。
    2017-06-06
  • golang高性能的http請求 fasthttp詳解

    golang高性能的http請求 fasthttp詳解

    fasthttp 是 Go 的快速 HTTP 實(shí)現(xiàn),當(dāng)前在 1M 并發(fā)的生產(chǎn)環(huán)境使用非常成功,可以從單個服務(wù)器進(jìn)行 100K qps 的持續(xù)連接,總而言之,fasthttp 比 net/http 快 10 倍,下面通過本文給大家介紹golang fasthttp http請求的相關(guān)知識,一起看看吧
    2021-09-09
  • Golang中interface是引用類型的原因解析

    Golang中interface是引用類型的原因解析

    在Go語言中,將interface設(shè)計為引用類型是為了實(shí)現(xiàn)更靈活、更動態(tài)的類型系統(tǒng),這篇文章主要介紹了深度解析Golang中為什么interface是引用類型,需要的朋友可以參考下
    2024-01-01
  • Golang中g(shù)orm無法將字段更新為空值

    Golang中g(shù)orm無法將字段更新為空值

    本文主要介紹了Golang中g(shù)orm無法將字段更新為空值,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05

最新評論

仁寿县| 闽侯县| 安福县| 嘉黎县| 寿宁县| 长宁区| 沙河市| 布尔津县| 稻城县| 保康县| 客服| 汉川市| 博白县| 湟源县| 山东省| 攀枝花市| 海阳市| 准格尔旗| 二手房| 神池县| 昌平区| 广昌县| 布尔津县| 和硕县| 德令哈市| 昌江| 五指山市| 定日县| 库尔勒市| 霸州市| 德昌县| 通榆县| 绍兴县| 衡东县| 灵璧县| 长子县| 咸阳市| 三门峡市| 南丹县| 乌兰浩特市| 历史|