欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Go语言中定时器的使用

程序员文章站 2022-04-16 09:34:09
GO语言在time包中提供了三种定时器的使用方式: 1.第一种:ticker // A Ticker holds a channel that delivers `ticks' of a clock // at intervals. type Ticker struct { C <-chan Tim ......

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\n", 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\n", 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 }

 

部分执行结果截图:

Go语言中定时器的使用

 

最后补充一下,通过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语言中定时器的使用

 

 

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