Ticker Or Sleep?定時執(zhí)行的新選擇
在寫 Python 的時候,如果想讓某個函數(shù)每 60 秒執(zhí)行一次,我們一般這樣寫代碼:
- import time
- while True:
- some_function()
- time.sleep(60)
于是,我在寫 Golang 代碼的時候,也使用了這種方式:
- package main
- import (
- "fmt"
- "time"
- )
- func someFunction() {
- fmt.Println("我是某個函數(shù)")
- }
- func main() {
- for {
- someFunction()
- time.Sleep(10 * time.Second)
- }
- }
今天在看同事的代碼時,發(fā)現(xiàn)他是這樣寫的:
- package main
- import (
- "fmt"
- "time"
- )
- func someFunction() {
- fmt.Println("我是某個函數(shù)")
- }
- func main() {
- tikcer := time.NewTicker(10 * time.Second)
- for {
- <-tikcer.C
- someFunction()
- }
- }
這種寫法,初看起來時跟time.Sleep沒什么區(qū)別,但是仔細(xì)一想,卻發(fā)現(xiàn)它有很多優(yōu)勢。
首先,NewTicker會在背后計時,時間到了以后,會向內(nèi)部的一個 channel 中推入當(dāng)前的時間。然后繼續(xù)計時。所以,如果函數(shù)someFunction()執(zhí)行了3秒鐘。那么接下來過7秒就會繼續(xù)執(zhí)行。但如果使用time.Sleep,函數(shù)執(zhí)行完成以后,還要再等10秒鐘才會執(zhí)行。
其次,如果不啟動新的協(xié)程,那么當(dāng)執(zhí)行到time.Sleep時,整個程序是卡住的,必須等待它結(jié)束了才能執(zhí)行后面的操作。但如果使用 NewTicker,那么在等待的時間,還可以做很多其他的事情。多個不同的定時器可以同時工作:
- package main
- import (
- "fmt"
- "time"
- )
- func someFunction() {
- fmt.Println("我是某個函數(shù)")
- }
- func anotherFunction() {
- fmt.Println("另一個函數(shù)")
- }
- func thirdFunction() {
- fmt.Println("第三個函數(shù)")
- }
- func main() {
- tikcer1 := time.NewTicker(10 * time.Second)
- tikcer2 := time.NewTicker(5 * time.Second)
- tikcer3 := time.NewTicker(3 * time.Second)
- for {
- select {
- case <-tikcer1.C:
- someFunction()
- case <-tikcer2.C:
- anotherFunction()
- case <-tikcer3.C:
- thirdFunction()
- }
- }
- }
這樣可以實現(xiàn),每3秒執(zhí)行 thirdFunction函數(shù),每5秒執(zhí)行anotherFunction,每10秒執(zhí)行一次someFunction。大家可以考慮一下,如何用 time.Sleep來實現(xiàn)這樣的功能。
注意每個函數(shù)都是獨立計時的,只要他們執(zhí)行的時間不超過他們間隔的時間,就不會互相影響。
除了全部用來計時外,我們還可以用來設(shè)置外部開關(guān),中斷一個協(xié)程。例如:
- package main
- import (
- "fmt"
- "time"
- )
- func doSomething() {
- fmt.Println("進(jìn)行某些操作")
- }
- func someFunction(stop chan bool) {
- fmt.Println("我是某個函數(shù)")
- tikcer1 := time.NewTicker(10 * time.Second)
- for {
- select {
- case <-tikcer1.C:
- doSomething()
- case <-stop:
- return
- }
- }
- }
- func main() {
- stop := make(chan bool)
- go someFunction(stop)
- //很多行代碼
- //很多行代碼
- //很多行代碼
- stop <- true
- //其他代碼
- //其他代碼
- }
在協(xié)程里面是一個10秒執(zhí)行一次的定時函數(shù)。但是我們可以在外面控制這個協(xié)程,從而隨時停止這個協(xié)程。
本文轉(zhuǎn)載自微信公眾號「未聞Code」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系未聞Code公眾號。