網(wǎng)站首頁 編程語言 正文
前言
定時(shí)器在Go語言應(yīng)用中使用非常廣泛,Go語言的標(biāo)準(zhǔn)庫里提供兩種類型的計(jì)時(shí)器,一種是一次性的定時(shí)器Timer
,另外一種是周期性的定時(shí)器Ticker
。本文主要來看一下Ticker
的用法和實(shí)現(xiàn)原理,需要的朋友可以參考以下內(nèi)容,希望對大家有幫助。
Ticker
Ticker是周期性定時(shí)器,即周期性的觸發(fā)一個(gè)事件,它會以一個(gè)間隔(interval)往channel發(fā)送一個(gè)事件(當(dāng)前時(shí)間),而channel的接收者可以以固定的時(shí)間間隔從channel中讀取事件。通過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í)器對外暴露的 Stop 方法就可以停掉一個(gè)周期性定時(shí)器, 函數(shù)如下:
func (t *Ticker) Stop()
該方法會停止計(jì)時(shí),停止后不會向定時(shí)器的管道中寫入事件,但管道并不會被關(guān)閉。
管道在使用完成后,生命周期結(jié)束后會自動(dòng)釋放。
實(shí)現(xiàn)原理
數(shù)據(jù)結(jié)構(gòu)
Ticker的數(shù)據(jù)結(jié)構(gòu)與Timer完全一致:
通過src/time.sleep.go:Ticker
定義了Timer
數(shù)據(jù)結(jié)構(gòu):
type Ticker struct { C <-chan Time r runtimeTimer }
它提供了一個(gè)channel
,在定時(shí)時(shí)間到達(dá)之前,沒有數(shù)據(jù)寫入Ticker.C
會一直阻塞,直到時(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)控,我們通過設(shè)置runtimeTimer過期后的行為來達(dá)到定時(shí)的目的。
源碼包src/time/sleep.go:runtimeTimer定義了其數(shù)據(jù)結(jié)構(gòu):
type runtimeTimer struct { tb uintptr // 存儲當(dāng)前定時(shí)器的數(shù)組地址 i int // 存儲當(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ā)場景下使用) }
創(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通過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并不會關(guān)閉管道,以避免用戶協(xié)程讀取錯(cuò)誤。
注意:
Ticker在使用完后務(wù)必要釋放,否則會產(chǎn)生資源泄露,進(jìn)而會持續(xù)消耗CPU資源,最后會把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()來創(chuàng)建一個(gè)定時(shí)器;
- 使用Stop()來停止一個(gè)定時(shí)器;
- 定時(shí)器使用完畢要釋放,否則會產(chǎn)生資源泄露;
原文鏈接:https://juejin.cn/post/7135368112584687623
相關(guān)推薦
- 2021-12-02 C/C++?Qt數(shù)據(jù)庫SqlRelationalTable關(guān)聯(lián)表詳解_C 語言
- 2022-09-08 深入了解Go語言的基本語法與常用函數(shù)_Golang
- 2022-12-25 Python中你所不知道的星號?*?用法_python
- 2022-04-15 python使用reportlab生成pdf實(shí)例_python
- 2022-09-03 Python?Pandas多種添加行列數(shù)據(jù)方法總結(jié)_python
- 2022-04-05 Go語言空結(jié)構(gòu)體詳解_Golang
- 2022-01-02 無法將“node.exe”項(xiàng)識別為 cmdlet、函數(shù)、腳本文件或可運(yùn)行程序的名稱
- 2022-04-09 MyBatis 查詢返回?cái)?shù)據(jù)類型Map,空字段數(shù)據(jù)不返回
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支