zoukankan      html  css  js  c++  java
  • Go语言中定时器的使用

    GO语言在time包中提供了三种定时器的使用方式:

    1.第一种:ticker

    // A Ticker holds a channel that delivers `ticks' of a clock
    // at intervals.
    type Ticker struct {
    	C <-chan Time // The channel on which the ticks are delivered.
    	r runtimeTimer
    }
    

     通过 time.NewTicker() 创建,这种类型,ticker会不断的按照设定的间隔时间触发,除非主动终止运行。

    2.第二种:timer

    // The Timer type represents a single event.
    // When the Timer expires, the current time will be sent on C,
    // unless the Timer was created by AfterFunc.
    // A Timer must be created with NewTimer or AfterFunc.
    type Timer struct {
    	C <-chan Time
    	r runtimeTimer
    }
    

     通过 time.NewTimer() 创建,这种类型,timer只会执行一次,当然,可以在执行完以后通过调用 timer.Reset() 让定时器再次工作,并可以更改时间间隔。

    3.第三种:After()

    // After waits for the duration to elapse and then sends the current time
    // on the returned channel.
    // It is equivalent to NewTimer(d).C.
    // The underlying Timer is not recovered by the garbage collector
    // until the timer fires. If efficiency is a concern, use NewTimer
    // instead and call Timer.Stop if the timer is no longer needed.
    func After(d Duration) <-chan Time {
    	return NewTimer(d).C
    }
    

     从代码可以看到,After()其实是Timer的一个语法糖。


    下面通过代码演示一下三种方式的使用:

    1.Ticker

     1     ticker := time.NewTicker(time.Second * 1) // 运行时长
     2     ch := make(chan int)
     3     go func() {
     4         var x int
     5         for x < 10 {
     6             select {
     7             case <-ticker.C:
     8                 x++
     9                 fmt.Printf("%d
    ", x)
    10             }
    11         }
    12         ticker.Stop()
    13         ch <- 0
    14     }()
    15     <-ch                                    // 通过通道阻塞,让任务可以执行完指定的次数。

    该ticker每1秒触发一次,即ticker.C中每一秒会有一个内容加入,最后通过向ch中写入数字,让程序解除阻塞,继续执行。

    2.Timer

     1     timer := time.NewTimer(time.Second * 1) // timer 只能按时触发一次,可通过Reset()重置后继续触发。
     2     go func() {
     3         var x int
     4         for {
     5             select {
     6             case <-timer.C:
     7                 x++
     8                 fmt.Printf("%d,%s
    ", x, time.Now().Format("2006-01-02 15:04:05"))
     9                 if x < 10 {
    10                     timer.Reset(time.Second * 2)
    11                 } else {
    12                     ch <- x
    13                 }
    14             }
    15         }
    16     }()
    17     <-ch

    3.After()

     1     // 阻塞一下,等待主进程结束
     2     tt := time.NewTimer(time.Second * 10)
     3     <-tt.C
     4     fmt.Println("over.")
     5 
     6     <-time.After(time.Second * 4)
     7     fmt.Println("再等待4秒退出。tt 没有终止,打印出 over 后会看见在继续执行...")
     8     tt.Stop()
     9     <-time.After(time.Second * 2)
    10     fmt.Println("tt.Stop()后, tt 仍继续执行,只是关闭了 tt.C 通道。")

    4.我们可以利用这些基本的方法,设计自己的定时任务管理。

     1 type jobFunc2 func(j *job)
     2 
     3 type job struct {
     4     jf     jobFunc2
     5     params map[string]interface{}
     6     ch     chan int
     7 }
     8 
     9 func NewJob() *job {
    10     return &job{
    11         params: make(map[string]interface{}),
    12         ch:     make(chan int),
    13     }
    14 }
    15 
    16 func (j *job) Run(t time.Duration) {
    17     ticker := time.NewTicker(time.Second * t)
    18     go func() {
    19         for {
    20             select {
    21             case <-ticker.C:
    22                 j.jf(j)
    23             case <-j.ch:
    24                 fmt.Println("收到结束指令")
    25                 ticker.Stop()
    26                 break
    27             }
    28         }
    29     }()
    30     
    31 }
    32 
    33 func main() {
    34     j := NewJob()
    35     j.jf = func(jj *job) {
    36         fmt.Println("定时任务执行...", time.Now().Format("15:04:05 2006-02-01"), jj.params)
    37     }
    38     j.params["p1"] = "第一个参数"
    39     j.params["p2"] = 100
    40     j.Run(1)
    41 
    42     // 阻塞一下,等待主进程结束
    43     tt := time.NewTimer(time.Second * 10)
    44     <-tt.C
    45     fmt.Println("over.")
    46 
    47     <-time.After(time.Second * 4)
    48     fmt.Println("再等待4秒退出。tt 没有终止,打印出 over 后会看见在继续执行...")
    49     tt.Stop()
    50     <-time.After(time.Second * 2)
    51     fmt.Println("tt.Stop()后, tt 仍继续执行,只是关闭了 tt.C 通道。")
    52 }

    部分执行结果截图:

    最后补充一下,通过channel去终止任务的执行。

     1     // 阻塞一下,等待主进程结束
     2     tt := time.NewTimer(time.Second * 10)
     3     <-tt.C
     4     fmt.Println("over.")
     5 
     6     <-time.After(time.Second * 4)
     7     fmt.Println("再等待4秒退出。tt 没有终止,打印出 over 后会看见在继续执行...")
     8     tt.Stop()
     9     <-time.After(time.Second * 2)
    10     fmt.Println("tt.Stop()后, tt 仍继续执行,只是关闭了 tt.C 通道。")
    11     j.ch <- 0
    12     <-time.After(time.Second * 2)
    13     fmt.Println("又等了2秒钟...这两秒钟可以看到 tt 没干活了...")

     

    在GO语言编写中,要熟练使用 channel

  • 相关阅读:
    sql中的不常见查询
    sql中的常见报错;
    wcf_first
    均方值-数学期望-方差
    转:模块度(Modularity)与Fast Newman算法讲解与代码实现
    转:社区发现评估指标-NMI
    转:模块度(Modularity)与Fast Newman算法讲解与代码实现
    转:聚类评价指标
    转:聚类︱python实现 六大 分群质量评估指标(兰德系数、互信息、轮廓系数)
    转:用K-Means聚类分析做客户分群
  • 原文地址:https://www.cnblogs.com/codingnote/p/12469098.html
Copyright © 2011-2022 走看看