定时器 和 断续器
定时器:延时某些操作任务
断续器:设置的好间隔时间,周而复始的执行任务
package main
import (
"fmt"
"time"
)
// 定时器 和 断续器
/**
定时器:延时某些操作任务
断续器:设置的好间隔时间,周而复始的执行任务
有两种方式创建定时器:
time.NewTimer 函数 和 time.AfterFunc 函数
这两个函数将得到 time.Timer 类型
// timer.Reset(time.Second * 3) 重置定时器,并设置定时器间隔时间
// timer.Stop() 停止定时器
// time.Sleep(time.Second) // 睡眠,一秒
timer.Reset(...) 和 timer.Sleep() 返回值是一个 bool 值。
如果值为 false 表示,这个定时器已经过期(或者结束了),
如果值为 true 表示,已经成功 重置 或者 停止
time.NewTimer 函数 和 time.AfterFunc 函数 创建的定时器只能执行一次,
需要配合 for 和 select 才能周而复始的执行
断续器:
time.NewTicker 函数创建, 可以周而复始的执行,比如每次间隔3秒执行一次任务
**/
// ======================== 定时器
// 定时器例子 time.NewTimer 方式
func timer1() {
// 这里的定时器,执行完就会结束(因为main函数结束了),如果想周而复始的执行,使用 for 和 select 方式
// 创建一个到期时间的间隔为 3 秒的定时器
// 参数 time.Duration 类型
timer := time.NewTimer(time.Second * 3)
fmt.Printf("定时器开始时间:%v\n", time.Now().Format("2006-01-02 15:04:05"))
// <-timer.C 表示接收这个管道的值, 传递过来的是它到期的时间
// 间隔一段时间执行下面的代码, 管道有值表示定时器的执行任务的时间到了
expTime := <-timer.C
fmt.Printf("定时器结束时间:%v\n", time.Now().Format("2006-01-02 15:04:05"))
// 指定自定义的时间进行格式化
// time.Parse("2006-01-02 15:04:05", "2020-10-01 10:10:01")
fmt.Printf("接收定时器管道的值:%v", expTime.Format("2006-01-02 15:04:05"))
fmt.Printf("停止定时器:%v", timer.Stop())
// timer.Reset(time.Second * 3) 重置定时器,并设置定时器间隔时间
// timer.Stop() 停止定时器
// time.Sleep(time.Second) // 睡眠,一秒
}
// 定时器例子 time.AfterFunc 方式
func timer2() {
// 这里的定时器,执行完就会结束(因为main函数结束了),如果想周而复始的执行,使用 select 方式
// 创建一个到期时间的间隔为 3 秒的定时器
time.AfterFunc(time.Second*3, func() {
// 我需要执行操作...
fmt.Printf("定时器执行中!")
})
// time.AfterFunc 函数不会往 C <- timer.C 管道中发送数据,而是启用 goroutine 去执行传递进去的函数
}
// 定时器例子
// 上面的例子,会发现只执行了一次,
// 这个例子适用于指定我们需要执行的次数
// 这里使用 time.NewTimer 做例子
func timer3() {
t := time.Second * 3
var timer *time.Timer
// 执行任务的通信管道
intChan := make(chan int, 1)
go func() {
// 设置需要执行次数
// 比如只需执行两次
for i := 0; i < 2; i++ {
intChan <- i
time.Sleep(time.Second)
}
// 关闭这个管道
close(intChan)
}()
for {
if timer == nil {
timer = time.NewTimer(t)
} else {
// 通过 timer.Reset 函数重置这个定时器,达到目的
// 将超时时间重置
timer.Reset(t)
}
// 堵塞,谁有数据,就执行谁
// 只会执行一次
// 如果配合 for 死循环,可以达到一直监听管道的目的
select {
case e, ok := <-intChan:
// 如果管道关闭,表示这个 intChan 管道不可用使用,那么这个 ok 就是 false
if !ok {
// 结束这个定时器
return
}
fmt.Printf("定时器正在执行任务!时间:%v\t, 管道值:%v\n", time.Now().Format("2006-01-02 15:04:05"), e)
case <-timer.C:
// 如果 intChan 超过 3秒 没有数据,则会执行
fmt.Printf("超时!\n")
}
}
}
// 定时器例子,达到 断续器 的效果,周而复始执行
func timer4() {
t := time.Second * 3
var timer *time.Timer
for {
if timer == nil {
timer = time.NewTimer(t)
} else {
// 通过 timer.Reset 函数重置这个定时器,达到目的
// 将超时时间重置
timer.Reset(t)
}
// 堵塞,谁有数据,就执行谁
// 只会执行一次
// 如果配合 for 死循环,可以达到一直监听管道的目的
select {
case <-timer.C:
fmt.Printf("执行任务,当前时间:%v\n", time.Now().Format("2006-01-02 15:04:05"))
}
}
}
// ====================== 断续器
// 周而复始的执行
func timer5() {
ticker := time.NewTicker(time.Second * 3)
for {
select {
case <-ticker.C:
fmt.Printf("执行任务,当前时间:%v\n", time.Now().Format("2006-01-02 15:04:05"))
}
}
// ticker.Stop() 停止断续器
}
func main() {
go timer4()
// 主线程 睡眠 10 秒
time.Sleep(time.Second * 10)
}
网友评论