热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Go(Golang)语言Golang定时器Timer和Ticker、time.AfterFunc、time.NewTicker()实例

文章目录Golang定时器Timer和Tickertime.Timertime.NewTimer()实例time.AfterFunctime.Tickertime.NewTicke

文章目录

  • Golang 定时器Timer和Ticker
    • time.Timer
      • time.NewTimer()实例
    • time.AfterFunc
    • time.Ticker
      • time.NewTicker()实例
      • [重要]time.NewTicker()使用总结


Golang 定时器Timer和Ticker

Golang 定时器包括:一次性定时器(Timer)和周期性定时器(Ticker)。

编程中经常会通过timer和ticker、AfterFunc定时器NewTicker是设定每隔多长时间触发的,是连续触发,而计时器NewTimer是等待多长时间触发的,只触发一次,两者是不同的。等待时间函数AfterFunc是在After基础上加了一个回调函数,是等待时间到来后在另外一个goroutine协程里调用。

  • Timer
    timer创建有两种方式,time.NewTimer(Duration) 和time.After(Duration)。 后者只是对前者的一个包装。
    timer到固定时间后会执行一次,请注意是一次,而不是多次。但是可以通过reset来实现每隔固定时间段执行。使用timer定时器,超时后需要重置,才能继续触发。

  • Ticker
    ticker只要定义完成,从此刻开始计时,不需要任何其他的操作,每隔固定时间都会触发。它会以一个间隔(interval)往通道发送当前时间,而通道的接收者可以以固定的时间间隔从通道中读取时间。


time.Timer

首先我们看Timer的结构定义:

type Timer struct {C <-chan Timer runtimeTimer
}

其中有一个C的只读channel&#xff0c;还有一个runtimeTimer类型的结构体&#xff0c;再看一下这个结构的具体结构&#xff1a;

type runtimeTimer struct {tb uintptri intwhen int64period int64f func(interface{}, uintptr) // NOTE: must not be closurearg interface{}seq uintptr
}

在使用定时timer的时候都是通过 NewTimer 或 AfterFunc 函数来获取。

func NewTimer(d Duration) *Timer {c :&#61; make(chan Time, 1)t :&#61; &Timer{C: c,r: runtimeTimer{when: when(d), //表示达到时间段d时候调用ff: sendTime, // f表示一个函数调用&#xff0c;这里的sendTime表示d时间到达时向Timer.C发送当前的时间arg: c, // arg表示在调用f的时候把参数arg传递给f&#xff0c;c就是用来接受sendTime发送时间的},}startTimer(&t.r)return t
}

定时器的具体实现逻辑&#xff0c;都在 runtime 中的 time.go 中&#xff0c;它的实现&#xff0c;没有采用经典 Unix 间隔定时器 setitimer 系统调用&#xff0c;也没有 采用 POSIX间隔式定时器&#xff08;相关系统调用&#xff1a;timer_create、timer_settime 和 timer_delete&#xff09;&#xff0c;而是通过四叉树堆(heep)实现的&#xff08;runtimeTimer 结构中的i字段&#xff0c;表示在堆中的索引&#xff09;。通过构建一个最小堆&#xff0c;保证最快拿到到期了的定时器执行。定时器的执行&#xff0c;在专门的 goroutine 中进行的&#xff1a;go timerproc()。有兴趣的同学&#xff0c;可以阅读 runtime/time.go 的。

time.NewTimer()实例

package mainimport ("fmt""time"
)func main() {myTimer :&#61; time.NewTimer(time.Second * 2) // 启动定时器var i int &#61; 0for {select {case <-myTimer.C:i&#43;&#43;fmt.Println("count: ", i)myTimer.Reset(time.Second * 2) // 每次使用完后需要人为重置下}}// 不再使用了&#xff0c;结束它myTimer.Stop()
}

使用timer定时器&#xff0c;超时后需要重置&#xff0c;才能继续触发。

time.AfterFunc

Go语言的AfterFunc()函数用于等待经过的时间&#xff0c;此后&#xff0c;它将在其自己的go-routine中调用已定义的函数“f”。此外&#xff0c;此函数在时间包下定义。在这里&#xff0c;您需要导入“time”包才能使用这些函数。

func AfterFunc(d Duration, f func()) *Timer

例子&#xff1a;

// Golang program to illustrate the usage of
// AfterFunc() function // Including main package
package main // Importing fmt and time
import ( "fmt""time"
) // Main function
func main() { // Defining duration parameter of // AfterFunc() method DurationOfTime:&#61; time.Duration(3) * time.Second // Defining function parameter of // AfterFunc() method f:&#61; func() { // Printed when its called by the // AfterFunc() method in the time // stated above fmt.Println("Function called by "&#43; "AfterFunc() after 3 seconds") } // Calling AfterFunc() method with its // parameter Timer1:&#61; time.AfterFunc(DurationOfTime, f) // Calling stop method // w.r.to Timer1 defer Timer1.Stop() // Calling sleep method time.Sleep(10 * time.Second)
}

time.Ticker

官网&#xff1a;https://pkg.go.dev/time#NewTicker

Golang time.Timer and time.Ticker
参考URL: https://www.jianshu.com/p/2b4686b8de4a

time.NewTicker()实例

官网&#xff1a;https://pkg.go.dev/time#NewTicker

官方demo

package mainimport ("fmt""time"
)func main() {ticker :&#61; time.NewTicker(time.Second)defer ticker.Stop()done :&#61; make(chan bool)go func() {time.Sleep(10 * time.Second)done <- true}()for {select {case <-done:fmt.Println("Done!")returncase t :&#61; <-ticker.C:fmt.Println("Current time: ", t)}}
}

Ticker是一个周期触发定时的计时器&#xff0c;它会按照一个时间间隔往channel发送系统当前时间&#xff0c;而channel的接收者可以以固定的时间间隔从channel中读取事件。

相关函数&#xff1a;
NewTicker() 返回一个新的Ticker&#xff0c;该Ticker包含一个通道字段&#xff0c;并会每隔时间段d就向该通道发送当时的时间。它会调整时间间隔或者丢弃tick信息以适应反应慢的接收者。如果d<&#61;0会panic。关闭该Ticker可以释放相关资源。
Stop() 关闭一个Ticker。在关闭后&#xff0c;将不会发送更多的tick信息。Stop不会关闭通道t.C&#xff0c;以避免从该通道的读取不正确的成功

demo2: time.NewTicker 周期时间到了&#xff0c;但是之前程序没有执行完,怎么处理&#xff1f;

package mainimport ("fmt""time"
)func main() {ticker :&#61; time.NewTicker(time.Second)defer ticker.Stop()done :&#61; make(chan bool)go func() {time.Sleep(10 * time.Second)done <- true}()for {select {case <-done:fmt.Println("Done!")returncase t :&#61; <-ticker.C:fmt.Println("Current time: ", t)time.Sleep(4 * time.Second)}}
}

经过代码验证&#xff1a;time.NewTicker定时触发执行任务&#xff0c;当下一次执行到来而当前任务还没有执行结束时&#xff0c;会等待当前任务执行完毕后再执行下一次任务。

[重要]time.NewTicker()使用总结


  1. ticker 创建完之后&#xff0c;不是马上就有一个 tick&#xff0c;第一个 tick 在 x 秒&#xff08;你自己写的&#xff09;之后
  2. Go语言的定时器实质是单向通道&#xff0c;time.Timer结构体类型中有一个time.Time类型的单向chan。
  3. **time.NewTicker定时触发执行任务&#xff0c;当下一次执行到来而当前任务还没有执行结束时&#xff0c;会等待当前任务执行完毕后再执行下一次任务。**查阅go官网的文档和经过代码验证。
  4. t.Stop()在这里并不会停止定时器。这是因为Stop会停止Timer&#xff0c;停止后&#xff0c;Timer不会再被发送&#xff0c;但是Stop不会关闭通道&#xff0c;防止读取通道发生错误。
    官方说明&#xff1a;Stop turns off a ticker. After Stop, no more ticks will be sent. Stop does not close the channel, to prevent a concurrent goroutine reading from the channel from seeing an erroneous “tick”.
    如果想停止定时器&#xff0c;只能让go程序自动结束。
  5. Ticker 跟 Timer 的不同之处&#xff0c;就在于 Ticker 时间达到后不需要人为调用 Reset 方法&#xff0c;会自动续期。

推荐阅读
  • 深入解析Java枚举及其高级特性
    本文详细介绍了Java枚举的概念、语法、使用规则和应用场景,并探讨了其在实际编程中的高级应用。所有相关内容已收录于GitHub仓库[JavaLearningmanual](https://github.com/Ziphtracks/JavaLearningmanual),欢迎Star并持续关注。 ... [详细]
  • 本题探讨了在一个有向图中,如何根据特定规则将城市划分为若干个区域,使得每个区域内的城市之间能够相互到达,并且划分的区域数量最少。题目提供了时间限制和内存限制,要求在给定的城市和道路信息下,计算出最少需要划分的区域数量。 ... [详细]
  • 本文介绍了Linux系统中的文件IO操作,包括文件描述符、基本文件操作函数以及目录操作。详细解释了各个函数的参数和返回值,并提供了代码示例。 ... [详细]
  • C语言基础入门:7个经典小程序助你快速掌握编程技巧
    本文精选了7个经典的C语言小程序,旨在帮助初学者快速掌握编程基础。通过这些程序的实践,你将更深入地理解C语言的核心概念和语法结构。 ... [详细]
  • #点球小游戏fromrandomimportchoiceimporttimescore[0,0]direction[left,center,right]defkick() ... [详细]
  • 本文探讨了在使用Selenium进行自动化测试时,由于webdriver对象实例化位置不同而导致浏览器闪退的问题,并提供了详细的代码示例和解决方案。 ... [详细]
  • 本文探讨了在C++中如何有效地清空输入缓冲区,确保程序只处理最近的输入并丢弃多余的输入。我们将介绍一种不阻塞的方法,并提供一个具体的实现方案。 ... [详细]
  • 本文详细介绍了 org.apache.commons.io.IOCase 类中的 checkCompareTo() 方法,通过多个代码示例展示其在不同场景下的使用方法。 ... [详细]
  • 本文介绍如何在SQL Server中创建动态SQL存储过程,并提供详细的代码实例和解释。通过这种方式,可以更灵活地处理查询条件和参数。 ... [详细]
  • JavaScript 基础语法指南
    本文详细介绍了 JavaScript 的基础语法,包括变量、数据类型、运算符、语句和函数等内容,旨在为初学者提供全面的入门指导。 ... [详细]
  • 利用决策树预测NBA比赛胜负的Python数据挖掘实践
    本文通过使用2013-14赛季NBA赛程与结果数据集以及2013年NBA排名数据,结合《Python数据挖掘入门与实践》一书中的方法,展示如何应用决策树算法进行比赛胜负预测。我们将详细讲解数据预处理、特征工程及模型评估等关键步骤。 ... [详细]
  • 中科院学位论文排版指南
    随着毕业季的到来,许多即将毕业的学生开始撰写学位论文。本文介绍了使用LaTeX排版学位论文的方法,特别是针对中国科学院大学研究生学位论文撰写规范指导意见的最新要求。LaTeX以其精确的控制和美观的排版效果成为许多学者的首选。 ... [详细]
  • 在现代Web应用中,当用户滚动到页面底部时,自动加载更多内容的功能变得越来越普遍。这种无刷新加载技术不仅提升了用户体验,还优化了页面性能。本文将探讨如何实现这一功能,并介绍一些实际应用案例。 ... [详细]
  • 本文详细介绍如何在Linux系统中配置SSH密钥对,以实现从一台主机到另一台主机的无密码登录。内容涵盖密钥对生成、公钥分发及权限设置等关键步骤。 ... [详细]
  • 本文详细介绍了如何在 Objective-C 中使用 @public 和 @protected 修饰符来控制类成员的访问权限。同时,探讨了点语法和箭头操作符的区别,以及属性声明和实现的自动生成。 ... [详细]
author-avatar
Sunny-虫虫
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有