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周期性定时器的资料请关注脚本之家其它相关文章!

相关文章

  • Windows10系统下安装Go环境详细步骤

    Windows10系统下安装Go环境详细步骤

    Go语言是谷歌推出的一款全新的编程语言,可以在不损失应用程序性能的情况下极大的降低代码的复杂性,这篇文章主要给大家介绍了关于Windows10系统下安装Go环境的详细步骤,需要的朋友可以参考下
    2023-11-11
  • go语言中proto文件的使用

    go语言中proto文件的使用

    在Go语言编程中,.proto文件用于定义Protocol Buffers数据结构和服务,是实现跨语言通信和高效序列化的关键,具有一定的参考价值,感兴趣的可以了解一下
    2024-10-10
  • Go实现SMTP邮件发送订阅功能(包含163邮箱、163企业邮箱、谷歌gmail邮箱)

    Go实现SMTP邮件发送订阅功能(包含163邮箱、163企业邮箱、谷歌gmail邮箱)

    这篇文章给大家介绍了Go实现SMTP邮件发送订阅功能(包含163邮箱、163企业邮箱、谷歌gmail邮箱),需求很简单,就是用户输入自己的邮箱后,使用官方邮箱给用户发送替邮件模版,文中有详细的代码示例供大家参考,需要的朋友可以参考下
    2023-10-10
  • 一文详解Golang中的基础语法

    一文详解Golang中的基础语法

    这篇文章主要为大家详细介绍了Golang中基础语法的相关知识,文中的示例代码讲解详细,对我们学习Golang有一定的帮助,感兴趣的可以了解一下
    2023-03-03
  • go goroutine 怎样进行错误处理

    go goroutine 怎样进行错误处理

    在 Go 语言程序开发中,goroutine 的使用是比较频繁的,因此在日常编码的时候 goroutine 里的错误处理,怎么做会比较好呢,本文就来详细介绍一下
    2021-07-07
  • Web框架Gin中间件实现原理步骤解析

    Web框架Gin中间件实现原理步骤解析

    这篇文章主要为大家介绍了Web框架Gin中间件实现原理步骤解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • Go语言中循环语句使用的示例详解

    Go语言中循环语句使用的示例详解

    在不少实际问题中有许多具有规律性的重复操作,因此在程序中就需要重复执行某些语句。本文将通过示例详细为大家讲讲Go语言中的循环语句,需要的可以参考一下
    2022-04-04
  • golang 实现并发求和

    golang 实现并发求和

    这篇文章主要介绍了golang 并发求和的实现方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-05-05
  • golang gc的内部优化详细介绍

    golang gc的内部优化详细介绍

    Go编译器在垃圾回收(GC)的扫描标记阶段,对存储无指针键值对的map进行了优化,即在GC扫描时不深入扫描map内部数据,只检查map本身是否需要回收,这一优化显著提升了GC扫描的速度,从而减少了GC对程序性能的影响
    2024-10-10
  • 使用Go语言中的Context取消协程执行的操作代码

    使用Go语言中的Context取消协程执行的操作代码

    在 Go 语言中,协程(goroutine)是一种轻量级的线程,非常适合处理并发任务,然而,如何优雅地取消正在运行的协程是一个常见的问题,本文将通过一个具体的例子来展示如何使用 context 包来取消协程的执行,需要的朋友可以参考下
    2024-11-11

最新评论