網站首頁 編程語言 正文
前言
定時器在Go語言應用中使用非常廣泛,Go語言的標準庫里提供兩種類型的計時器,一種是一次性的定時器Timer
,另外一種是周期性的定時器Ticker
。本文主要來看一下Ticker
的用法和實現原理,需要的朋友可以參考以下內容,希望對大家有幫助。
Ticker
Ticker是周期性定時器,即周期性的觸發一個事件,它會以一個間隔(interval)往channel發送一個事件(當前時間),而channel的接收者可以以固定的時間間隔從channel中讀取事件。通過Ticker本身提供的管道將事件傳遞出去。
應用示例
package main import ( "fmt" "time" ) func main() { ticker := time.NewTicker(time.Second * 1) //創建一個周期性定時器 i := 1 for { fmt.Println(i, "====>", <-ticker.C) if i == 5 { ticker.Stop() //停止定時器 break } i++ } }
輸出結果:
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
創建定時器
使用NewTicker()方法就可以創建一個周期性定時器,函數如下:
func NewTicker(d Duration) *Ticker
其中參數d即為定時器時間觸發的周期,為一個時間段。
停止定時器
使用定時器對外暴露的 Stop 方法就可以停掉一個周期性定時器, 函數如下:
func (t *Ticker) Stop()
該方法會停止計時,停止后不會向定時器的管道中寫入事件,但管道并不會被關閉。
管道在使用完成后,生命周期結束后會自動釋放。
實現原理
數據結構
Ticker的數據結構與Timer完全一致:
通過src/time.sleep.go:Ticker
定義了Timer
數據結構:
type Ticker struct { C <-chan Time r runtimeTimer }
它提供了一個channel
,在定時時間到達之前,沒有數據寫入Ticker.C
會一直阻塞,直到時間到達,向channel
寫入系統時間,阻塞解除,可以從中讀取數據,這就是一個事件。
我們可以理解為Ticker.C
即面向Ticker
用戶的,Ticker.r
是面向底層的定時器實現。
runtimeTimer
runtimeTimer與Timer一樣,任務的載體,用于監控定時任務,每創建一個Timer就創建一個runtimeTimer變量,然后把它交給系統進行監控,我們通過設置runtimeTimer過期后的行為來達到定時的目的。
源碼包src/time/sleep.go:runtimeTimer定義了其數據結構:
type runtimeTimer struct { tb uintptr // 存儲當前定時器的數組地址 i int // 存儲當前定時器的數組下標 when int64 // 當前定時器觸發時間 period int64 // 當前定時器周期觸發間隔 f func(interface{}, uintptr) // 定時器觸發時執行的函數 arg interface{} // 定時器觸發時執行函數傳遞的參數一 seq uintptr // 定時器觸發時執行函數傳遞的參數二(該參數只在網絡收發場景下使用) }
創建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的重要區就是提供了period這個參數,據此決定timer是一次性的,還是周期性的 f: sendTime, arg: c, }, } startTimer(&t.r) return t }
NewTicker()構造了一個Ticker,然后把Ticker.r通過startTimer()交給系統協程維護。
其中period為事件觸發的周期。
停止Ticker
停止Ticker,只是把Ticker從系統協程中移除。
func (t *Ticker) Stop() { stopTimer(&t.r) }
stopTicker()即通知系統協程把該Ticker移除,即不再監控。系統協程只是移除Ticker并不會關閉管道,以避免用戶協程讀取錯誤。
注意:
Ticker在使用完后務必要釋放,否則會產生資源泄露,進而會持續消耗CPU資源,最后會把CPU耗盡。
ticker := time.NewTicker(1 * time.Second) defer ticker.Stop()
Ticker 與 Timer 區別
- Ticker —— 重復性執行任務非常有用呢
- Timer —— 用于執行一次性任務
小結
Ticker相關內容總結如下:
- 使用time.NewTicker()來創建一個定時器;
- 使用Stop()來停止一個定時器;
- 定時器使用完畢要釋放,否則會產生資源泄露;
原文鏈接:https://juejin.cn/post/7135368112584687623
相關推薦
- 2022-04-15 Python爬蟲之requests庫基本介紹_python
- 2022-09-18 iOS開發retina屏幕下的點與像素關系詳解_IOS
- 2022-08-11 C#實現快速查詢文件的方法_C#教程
- 2023-07-04 Linux直接創建SSH無密碼連接
- 2023-08-28 axios的使用和接口請求統一封裝處理
- 2022-11-20 C++遞歸算法處理島嶼問題詳解_C 語言
- 2023-06-18 C#中獲取文件大小問題_C#教程
- 2022-05-06 C語言枚舉的使用以及作用_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支