Hits

Go time包定时器、断续器

定时器

time包中有两个函数可以帮我们初始化 time.Timer (类型):

time.Newtimer()

初始化一个到期时间据此时的间隔3小时30分的定时器 t := time.Newtimer(3*time.Hour + 30*time.Minute) 其中 t*time.NewTimer 类型的,这个指针类型的方法集合包含两个方法:

  • Reset() 用于重置定时器,该方法返回一个bool类型的值
  • Stop() 用来停止定时器,该方法返回一个bool类型的值,如果返回false,说明该定时器在之前已经到期或者已经被停止了,反之返回true。

通过定时器的字段 C,我们可以及时得知定时器到期的这个事件来临,C 是一个 chan time.Time类型的缓冲通道,一旦触及到期时间,定时器就会向自己的 C 字段发送一个 time.Time类型的元素值

package main

import (
    "time"
    "fmt"
)

func main() {
    t := time.NewTimer(3 * time.Second)

    fmt.Printf("Time now = %v\n", time.Now())
    fmt.Printf("Expiration time = %v\n", <- t.C)
}
/** output:
Time now = 2018-11-27 09:22:09.92001771 +0800 CST m=+0.000332590
Expiration time = 2018-11-27 09:22:12.921125657 +0800 CST m=+3.001270537
*/

time.After()

  • time.Afer() 函数,表示多少时间之后,但是在取出 channel 内容之前不阻塞,后续程序可以继续执行。
  • 鉴于 After 特性,其通常用来处理程序超时问题。
package main

import (
    "time"
    "fmt"
)

func main() {
    ch1 := make(chan int, 1)
    ch2 := make(chan int, 1)
    // ch1 <- 1
    select {
    case e1 := <-ch1:
        //如果ch1通道成功读取数据,则执行该case处理语句
        fmt.Printf("1th case is selected. e1=%v", e1)
    case e2 := <-ch2:
        //如果ch2通道成功读取数据,则执行该case处理语句
        fmt.Printf("2th case is selected. e2=%v", e2)
    case <-time.After(2 * time.Second):
        fmt.Println("Timed out")
    }
}
// output: Timed out
  • time.Sleep() 函数,表示休眠多少时间,休眠时出于阻塞状态,后续程序无法执行。

time.Aferfunc() 函数

自定义定时器

package main

import (
    "fmt"
    "time"
)
func main(){
    var t *time.Timer

    f := func(){
        fmt.Printf("Expiration time : %v.\n", time.Now())
        fmt.Printf("C`s len: %d\n", len(t.C))
    }

    t = time.AfterFunc(1*time.Second, f)
    //让当前Goroutine 睡眠2s,确保大于内容的完整
    //这样做原因是,time.AfterFunc的调用不会被阻塞。它会以一部的方式在到期事件来临执行我们自定义函数f。
    time.Sleep(2 * time.Second)
}
/** output:
Expiration time : 2018-11-27 10:09:22.084781987 +0800 CST m=+1.003211639.
C`s len: 0
 */

第二行打印内容说明:定时器字段 C 并没有缓冲任何元素值,这也说明了,在给定了自定义函数后,默认的处理方法(向C发送代表绝对到期时间的元质素)就不会被执行了。

断续器

结构体类型 time.Ticker 表示了断续器的静态结构。

就是周期性的传达到期时间的装置,这种装置的行为方式与仅有秒针的钟表有些类似,只不过间隔时间可以不是1s.

初始化一个断续器: var ticker *time.Ticker = time.NewTicker(time.Second)

  • 使用时间控制停止 ticker
package main

import (
    "fmt"
    "time"
)

func main() {
    //初始化断续器,间隔2s
    var ticker *time.Ticker = time.NewTicker(1 * time.Second)

    go func() {
        for t := range ticker.C {
            fmt.Println("Tick at", t)
        }
    }()

    time.Sleep(time.Second * 5) //阻塞,则执行次数为sleep的休眠时间/ticker的时间
    ticker.Stop()
    fmt.Println("Ticker stopped")
}
/** output
Tick at 2018-11-27 10:22:23.621337572 +0800 CST m=+1.005007505
Tick at 2018-11-27 10:22:24.619869161 +0800 CST m=+2.003539094
Tick at 2018-11-27 10:22:25.616942037 +0800 CST m=+3.000443970
Tick at 2018-11-27 10:22:26.617859088 +0800 CST m=+4.001361021
Ticker stopped
 */
  • 使用channel控制停止ticker
package main

import (
    "fmt"
    "time"
)

func main(){
    //初始化断续器,间隔2s
    var ticker *time.Ticker = time.NewTicker(100 * time.Millisecond)

    //num为指定的执行次数
    num := 2
    c := make(chan int, num)
    go func() {
        for t := range ticker.C {
            c <- 1
            fmt.Println("Tick at", t)
        }
    }()

    time.Sleep(time.Millisecond * 1500)
    ticker.Stop()
    fmt.Println("Ticker stopped")
}
/** output
Tick at 2018-11-27 10:24:07.901315761 +0800 CST m=+0.100455175
Tick at 2018-11-27 10:24:08.002281616 +0800 CST m=+0.201341030
Ticker stopped
 */

本文链接:参与评论 »

--EOF--

专题「跟我一起学Go」的其它文章 »

Comments