## Timer原理
Timer實際上是一種單一事件的定時器,即經過指定的時間后觸發一個事件,這個事件通過其本身提供的channel進行通知。之所以叫單一事件,是因為Timer只執行一次就結束,這也是Timer與Ticker的最重要的區別之一。
通過timer.NewTimer(d Duration)可以創建一個timer,參數即等待的時間,時間到來后立即觸發一個事件。
源碼包`src/time/sleep.go:Timer`定義了Timer數據結構:
~~~go
type Timer struct { // Timer代表一次定時,時間到來后僅發生一個事件。
C <-chan Time
r runtimeTimer
}
~~~
Timer對外僅暴露一個channel,指定的時間到來時就往該channel中寫入系統時間,也即一個事件
## Timer使用場景
### 設定超時時間
有時我們希望從一個管道中讀取數據,在管道中沒有數據時,我們不想讓程序永遠阻塞在管道中,而是設定一個超時時間,在此時間段中如果管道中還是沒有數據到來,則判定為超時。
Go源碼包中有大量類似的用法,比如從一個連接中等待數據,其簡單的用法如下代碼所示:
~~~go
func WaitChannel(conn <-chan string) bool {
timer := time.NewTimer(1 * time.Second)
select {
case <- conn:
timer.Stop()
return true
case <- timer.C: // 超時
println("WaitChannel timeout!")
return false
}
}
~~~
WaitChannel作用就是檢測指定的管道中是否有數據到來,通過select語句輪詢conn和timer.C兩個管道,timer會在1s后向timer.C寫入數據,如果1s內conn還沒有數據,則會判斷為超時。
### 延遲執行某個方法
有時我們希望某個方法在今后的某個時刻執行,如下代碼所示:
~~~go
func DelayFunction() {
timer := time.NewTimer(5 * time.Second)
select {
case <- timer.C:
log.Println("Delayed 5s, start to do something.")
}
}
~~~
DelayFunction()會一直等待timer的事件到來才會執行后面的方法(打印)
延遲執行另外一個方法:AfterFunc()
~~~go
func AfterFunc(d Duration, f func()) *Timer
~~~
該方法在指定時間到來后會執行函數f。例如:
~~~go
func AfterFuncDemo() {
log.Println("AfterFuncDemo start: ", time.Now())
time.AfterFunc(1 * time.Second, func() {
log.Println("AfterFuncDemo end: ", time.Now())
})
time.Sleep(2 * time.Second) // 等待協程退出
}
~~~
AfterFuncDemo()中先打印一個時間,然后使用AfterFunc啟動一個定器,并指定定時器結束時執行一個方法打印結束時間。
注意:time.AfterFunc()是異步執行的,所以需要在函數最后sleep等待指定的協程退出,否則可能函數結束時協程還未執行
### 匿名定時器
`func After(d Duration) <-chan Time`方法創建一個定時器,并返回定時器的管道,如下代碼所示:
~~~go
func AfterDemo() {
log.Println(time.Now())
<- time.After(1 * time.Second)
log.Println(time.Now())
}
~~~
AfterDemo()兩條打印時間間隔為1s,實際還是一個定時器,但代碼變得更簡潔
### Timer使用案例
時間只執行1次
~~~
func main() {
// 1.timer基本使用
//timer1 := time.NewTimer(2 * time.Second)
//t1 := time.Now()
//fmt.Printf("t1:%v\n", t1)
//t2 := <-timer1.C
//fmt.Printf("t2:%v\n", t2)
// 2.驗證timer只能響應1次
//timer2 := time.NewTimer(time.Second)
//for {
// <-timer2.C
// fmt.Println("時間到")
//}
// 3.timer實現延時的功能
//(1)
//time.Sleep(time.Second)
//(2)
//timer3 := time.NewTimer(2 * time.Second)
//<-timer3.C
//fmt.Println("2秒到")
//(3)
//<-time.After(2*time.Second)
//fmt.Println("2秒到")
// 4.停止定時器
//timer4 := time.NewTimer(2 * time.Second)
//go func() {
// <-timer4.C
// fmt.Println("定時器執行了")
//}()
//b := timer4.Stop()
//if b {
// fmt.Println("timer4已經關閉")
//}
// 5.重置定時器
timer5 := time.NewTimer(3 * time.Second)
timer5.Reset(1 * time.Second)
fmt.Println(time.Now())
fmt.Println(<-timer5.C)
for {
}
}
~~~
多次執行
~~~
func main() {
// 1.獲取ticker對象
ticker := time.NewTicker(1 * time.Second)
i := 0
// 子協程
go func() {
for {
//<-ticker.C
i++
fmt.Println(<-ticker.C)
if i == 5 {
//停止
ticker.Stop()
}
}
}()
for {
}
}
~~~
- 概述
- go語言基礎特性
- Go語言聲明
- Go項目構建及編譯
- go command
- 程序設計原則
- Go基礎
- 變量
- 常量
- iota
- 基本類型
- byte和rune類型
- 類型定義和類型別名
- 數組
- string
- 高效字符串連接
- string底層原理
- 運算符
- new
- make
- 指針
- 下劃線 & import
- 語法糖
- 簡短變量申明
- 流程控制
- ifelse
- switch
- select
- select實現原理
- select常見案例
- for
- range
- range實現原理
- 常見案例
- range陷阱
- Goto&Break&Continue
- Go函數
- 函數
- 可變參數函數
- 高階函數
- init函數和main函數
- 匿名函數
- 閉包
- 常用內置函數
- defer
- defer常見案例
- defer規則
- defer與函數返回值
- defer實現原理
- defer陷阱
- 數據結構
- slice
- slice內存布局
- slice&array
- slice底層實現
- slice陷阱
- map
- Map實現原理
- 集合
- List
- Set
- 線程安全數據結構
- sync.Map
- Concurrent Map
- 面向對象編程
- struct
- 匿名結構體&匿名字段
- 嵌套結構體
- 結構體的“繼承”
- struct tag
- 行為方法
- 方法與函數
- type Method Value & Method Expressions
- interface
- 類型斷言
- 多態
- 錯誤機制
- error
- 自定義錯誤
- panic&recover
- reflect
- reflect包
- 應用示例
- DeepEqual
- 反射-fillObjectField
- 反射-copyObject
- IO
- 讀取文件
- 寫文件
- bufio
- ioutil
- Go網絡編程
- tcp
- tcp粘包
- udp
- HTTP
- http服務
- httprouter
- webSocket
- go并發編程
- Goroutine
- thread vs goroutine
- Goroutine任務取消
- 通過channel廣播實現
- Context
- Goroutine調度機制
- goroutine調度器1.0
- GMP模型調度器
- 調度器竊取策略
- 調度器的生命周期
- 調度過程全解析
- channel
- 無緩沖的通道
- 緩沖信道
- 單向信道
- chan實現原理
- 共享內存并發機制
- mutex互斥鎖
- mutex
- mutex原理
- mutex模式
- RWLock
- 使用信道處理競態條件
- WaitGroup
- 工作池
- 并發任務
- once運行一次
- 僅需任意任務完成
- 所有任務完成
- 對象池
- 定時器Timer
- Timer
- Timer實現原理
- 周期性定時器Ticker
- Ticker對外接口
- ticker使用場景
- ticker實現原理
- ticker使用陷阱
- 包和依賴管理
- package
- 依賴管理
- 測試
- 單元測試
- 表格測試法
- Banchmark
- BDD
- 常用架構模式
- Pipe-filter pattern
- Micro Kernel
- JSON
- json-內置解析器
- easyjson
- 性能分析
- gc
- 工具類
- fmt
- Time
- builtin
- unsafe
- sync.pool
- atomic
- flag
- runtime
- strconv
- template