日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

Go定時器的三種實現方式示例詳解_Golang

作者:機智的程序員小熊 ? 更新時間: 2023-01-19 編程語言

Sleep

很多時候需要周期性的執行某些操作,就需要用到定時器。定時器有三種思路。

本節源碼位置 github.com/golang-mini…

使用休眠,讓當前Goroutine休眠一定的時間來實現定時的效果,缺點是程序執行速度不均勻,導致定時周期不均勻。

for{
		fmt.Println(time.Now())
		time.Sleep(time.Second*1)
	}

Timer

Go 語言的內置包,指定一個時間開始計時,時間到之后會向外發送通知,發送通知的方式就是使用<-chan Time 返回內容。

第一種方式,直接在需要等待處使用,效果和Sleep一樣,一使用就卡在那了內部就是使用了Timer

	fmt.Println(time.Now())
	<-time.After(1*time.Second)
	fmt.Println(time.Now())

也可以把他拆分開,在任意地方進行等待

	timer := time.NewTimer(1 * time.Second)
	<-timer.C
	fmt.Println(time.Now())

但是以上只是做到延遲一次性執行,我們來改造一下,把他變成定時器。

    done := make(chan struct{})
	timer := time.NewTimer(1 * time.Second)
	go func() {
		for {
			select {
			case <-timer.C:
				fmt.Println(time.Now())
				timer.Reset(1 * time.Second)
			case <-done:
				return
			}
		}
	}()
	<-time.After(5*time.Second + time.Millisecond*100)
	done <- struct{}{}
  • 定義子Goroutine的目的是為了防止形成死鎖,讓定時器最終能退出,在實際項目中可能需要一個永久運行的定時器,一般為了不影響項目主邏輯也會這樣定義。如果你的項目就是定時任務,我建議也這么寫,這樣可以注冊很多個定時器互不影響。
  • done是為了判斷執行是否結束,防止主Goroutine提前退出。
  • 這個示例只有兩個case,實戰中如果有加其他case需要給每個case內都做一次Reset,保證重置定時器。

Ticker

相比上述使用延遲執行功能實現的定時器,Ticker 本身就是一個定時器(內部封裝了Timer),我們使用起來就非常簡單。

ticker := time.NewTicker(1 * time.Second)
	go func() {
		for {
			<-ticker.C
			fmt.Println(time.Now())
		}
	}()
	<-time.After(5 * time.Second + time.Millisecond*100)
	ticker.Stop()

在select 一節中講述的官方超時控制方案非常的實用,也是使用的此函數。還使用到timer.Stoptimer.Reset這兩個內置函數這里就不展開講解了,建議進行復習。

小結

定時器一般用來周期性執行任務,比如定時同步數據、計算報表、發送通知。

  • time.Sleep 使用休眠,讓當前goroutine休眠一定的時間來實現定時的效果,缺點是內部邏輯執行的速度會影響到定時器的時間差,無法做到精確間隔。
  • Timer 類似于Sleep的延遲處理,通過channel來獲得通知,也可以改造成定時器。因為是延遲處理,所以要記得重置時間來實現定時執行的效果。
  • Ticker 現成的定時器,內部也是封裝了 Timer

原文鏈接:https://juejin.cn/post/7178873205002600506

欄目分類
最近更新