Go Ticker 周期性定时器用法及实现原理详解

 更新时间:2022年08月25日 09:59:31   作者:yi个俗人  
这篇文章主要为大家介绍了Go Ticker 周期性定时器用法及实现原理详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

前言

定时器在Go语言应用中使用非常广泛,Go语言的标准库里提供两种类型的计时器,一种是一次性的定时器Timer,另外一种是周期性的定时器Ticker。本文主要来看一下Ticker的用法和实现原理,需要的朋友可以参考以下内容,希望对大家有帮助。

Ticker

Ticker是周期性定时器,即周期性的触发一个事件,它会以一个间隔(interval)往channel发送一个事件(当前时间),而channel的接收者可以以固定的时间间隔从channel中读取事件。通过Ticker本身提供的管道将事件传递出去。

应用示例

package main
import (
	"fmt"
	"time"
)
func main()  {
	ticker := time.NewTicker(time.Second * 1) //创建一个周期性定时器
	i := 1
	for  {
		fmt.Println(i, "====>", <-ticker.C)
		if i == 5 {
			ticker.Stop() //停止定时器
			break
		}
		i++
	}
}

输出结果:

1 ====> 2022-08-24 15:58:38.971837 +0800 CST m=+1.001366085
2 ====> 2022-08-24 15:58:39.971154 +0800 CST m=+2.000695418
3 ====> 2022-08-24 15:58:40.971633 +0800 CST m=+3.001185460
4 ====> 2022-08-24 15:58:41.97109 +0800 CST m=+4.000654126
5 ====> 2022-08-24 15:58:42.971594 +0800 CST m=+5.001169210

创建定时器

使用NewTicker()方法就可以创建一个周期性定时器,函数如下:

func NewTicker(d Duration) *Ticker

其中参数d即为定时器时间触发的周期,为一个时间段。

停止定时器

使用定时器对外暴露的 Stop 方法就可以停掉一个周期性定时器, 函数如下:

func (t *Ticker) Stop()

该方法会停止计时,停止后不会向定时器的管道中写入事件,但管道并不会被关闭。

管道在使用完成后,生命周期结束后会自动释放。

实现原理

数据结构

Ticker的数据结构与Timer完全一致:

通过src/time.sleep.go:Ticker定义了Timer数据结构:

type Ticker struct {
    C <-chan Time
    r runtimeTimer
}

它提供了一个channel,在定时时间到达之前,没有数据写入Ticker.C会一直阻塞,直到时间到达,向channel写入系统时间,阻塞解除,可以从中读取数据,这就是一个事件。

我们可以理解为Ticker.C即面向Ticker用户的,Ticker.r是面向底层的定时器实现。

runtimeTimer

runtimeTimer与Timer一样,任务的载体,用于监控定时任务,每创建一个Timer就创建一个runtimeTimer变量,然后把它交给系统进行监控,我们通过设置runtimeTimer过期后的行为来达到定时的目的。

源码包src/time/sleep.go:runtimeTimer定义了其数据结构:

type runtimeTimer struct {
    tb uintptr                          // 存储当前定时器的数组地址
    i  int                              // 存储当前定时器的数组下标
    when   int64                        // 当前定时器触发时间
    period int64                        // 当前定时器周期触发间隔
    f      func(interface{}, uintptr)   // 定时器触发时执行的函数
    arg    interface{}                  // 定时器触发时执行函数传递的参数一
    seq    uintptr                      // 定时器触发时执行函数传递的参数二(该参数只在网络收发场景下使用)
}

创建Ticker

func NewTicker(d Duration) *Ticker {
    if d <= 0 {
        panic(errors.New("non-positive interval for NewTicker"))
    }
    // Give the channel a 1-element time buffer.
    // If the client falls behind while reading, we drop ticks
    // on the floor until the client catches up.
    c := make(chan Time, 1)
    t := &Ticker{
        C: c,
        r: runtimeTimer{
            when:   when(d),
            period: int64(d), // Ticker跟Timer的重要区就是提供了period这个参数,据此决定timer是一次性的,还是周期性的
            f:      sendTime,
            arg:    c,
        },
    }
    startTimer(&t.r)
    return t
}

NewTicker()构造了一个Ticker,然后把Ticker.r通过startTimer()交给系统协程维护。

其中period为事件触发的周期。

停止Ticker

停止Ticker,只是把Ticker从系统协程中移除。

func (t *Ticker) Stop() {
    stopTimer(&t.r)
}

stopTicker()即通知系统协程把该Ticker移除,即不再监控。系统协程只是移除Ticker并不会关闭管道,以避免用户协程读取错误。

注意:

Ticker在使用完后务必要释放,否则会产生资源泄露,进而会持续消耗CPU资源,最后会把CPU耗尽。

ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()

Ticker 与 Timer 区别

  • Ticker —— 重复性执行任务非常有用呢
  • Timer —— 用于执行一次性任务

小结

Ticker相关内容总结如下:

  • 使用time.NewTicker()来创建一个定时器;
  • 使用Stop()来停止一个定时器;
  • 定时器使用完毕要释放,否则会产生资源泄露;

如果需要了解Timer,可以看这篇文章 https://www.jb51.net/article/260598.htm

以上就是Go Ticker 周期性定时器用法及实现原理详解的详细内容,更多关于Go Ticker周期性定时器的资料请关注脚本之家其它相关文章!

相关文章

  • Golang中四种gRPC模式举例详解

    Golang中四种gRPC模式举例详解

    gRPC是一种进程间通信技术,在微服务和云原生领域都有着广泛的应用,下面这篇文章主要给大家介绍了关于Golang中四种gRPC模式的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-03-03
  • Golang依赖注入工具digo的使用详解

    Golang依赖注入工具digo的使用详解

    这篇文章主要为大家详细介绍了Golang中依赖注入工具digo的使用,文中的示例代码讲解详细,具有一定的学习价值,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-06-06
  • Go编译原理之函数内联

    Go编译原理之函数内联

    这篇文章主要为大家介绍了Go编译原理之函数内联示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • Go语言中结构体的高级技巧分享

    Go语言中结构体的高级技巧分享

    这篇文章主要为大家分享一下Go语言中结构体的高级技巧,文中的示例代码讲解详细,具有一定的学习价值,感兴趣的小伙伴可以跟随小编一起了解一下
    2023-08-08
  • golang中判断请求是http还是https获取当前访问地址

    golang中判断请求是http还是https获取当前访问地址

    这篇文章主要为大家介绍了golang中判断请求是http还是https获取当前访问地址示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • Go单元测试对数据库CRUD进行Mock测试

    Go单元测试对数据库CRUD进行Mock测试

    这篇文章主要为大家介绍了Go单元测试对数据库CRUD进行Mock测试的示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • golang 在windows中设置环境变量的操作

    golang 在windows中设置环境变量的操作

    这篇文章主要介绍了golang 在windows中设置环境变量的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • go依赖注入库samber/do使用示例讲解

    go依赖注入库samber/do使用示例讲解

    这篇文章主要介绍了go依赖注入库samber/do使用,在本文中,我们学习了如何使用samber/do在 Go 中提供依赖注入,需要的朋友可以参考下
    2024-02-02
  • golang设置http response响应头与填坑记录

    golang设置http response响应头与填坑记录

    这篇文章主要给大家介绍了关于golang设置http response响应头与填坑记录的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-08-08
  • 一些关于Go程序错误处理的相关建议

    一些关于Go程序错误处理的相关建议

    错误处理在每个语言中都是一项重要内容,众所周知,通常写程序时遇到的分为异常与错误两种,Golang中也不例外,这篇文章主要给大家介绍了一些关于Go程序错误处理的相关建议,需要的朋友可以参考下
    2021-09-09

最新评论