正確使用Go的Timer

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

我們總是會使用Timer去執行一些定時任務,最近在Go語言的定時器使用上面不小心踩到一點問題,這裡記錄一下。

go demo(input)func demo(input chan interface{}) {    for {        select {        case msg <- input:            println(msg)        case <-time.After(time.Second * 5):            println("5s timer")        case <-time.After(time.Second * 10):            println("10s timer")        }    }}

寫出上面這段程式的目的是從 input channel 持續接收訊息加以處理,同時希望每過5秒鐘和每過10秒鐘就分別執行一個定時任務。但是當你執行這段程式的時候,只要 input channel 中的訊息來得足夠快,永不間斷,你會發現啟動的兩個定時任務都永遠不會執行;即使沒有訊息到來,第二個10s的定時器也是永遠不會執行的。原因就是 select 每次執行都會重新執行 case 條件陳述式,並重新註冊到 select 中,因此這兩個定時任務在每次執行 select 的時候,都是啟動了一個新的從頭開始計時的 Timer 對象,所以這兩個定時任務永遠不會執行。

其實,

select {case msg <- input:case <-time.After(time.Second)}

這個利用 time.After() 啟動 Timer 的編程手法主要是用來解決 channel 操作的 Timeout 問題,而不是執行定時任務。Go 語言採用這種方式來實現 channel 的 Timeout 究竟怎麼樣?這個話題暫時不在這裡分析。

如何正確使用 Timer 來完成上面提到的定時任務?

func demo(input chan interface{}) {    t1 := time.NewTimer(time.Second * 5)    t2 := time.NewTimer(time.Second * 10)    for {        select {        case msg <- input:            println(msg)        case <-t1.C:            println("5s timer")            t1.Reset(time.Second * 5)        case <-t2.C:            println("10s timer")            t2.Reset(time.Second * 10)        }    }}

改正後的程式,原理上是自訂兩個全域的 Timer,每次執行 select 都重複使用這兩個 Timer,而不是每次都產生全新的。這樣才可以真正做到在接收訊息的同時,還能夠定時的執行相應的任務。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.