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