当前位置: 首页 > news >正文

golang定时器

目录

一、什么是 Go 语言中的定时器?

基本概念

Go 语言中的实现

二、定时器的产生背景

  最原始的问题:程序需要“等待一段时间”

三、Go 定时器的内部实现原理

思想:

四、time.Timer —— 一次性定时器

1. 基本用法

2. 另一种方式:time.After

3.取消定时器:Stop()

4.重置定时器:Reset()

五、time.Ticker —— 周期性定时器

1.开启定时器。

2.停止定时器

六、定时器案例

1.用timer模拟闹钟贪睡

2.用ticker模拟心跳检测

七、总结

对比

选择场景

注意事项


一、什么是 Go 语言中的定时器?

基本概念

  • 定时器(Timer):就像一次性闹钟,设置后在指定时间触发一次事件,适合延迟执行或超时控制。

  • 计数器(Ticker):像每小时响一次的钟,定期重复触发事件,适合周期性任务。

Go 语言中的实现

Go 的 time 包提供了两个核心工具:

  • time.Timer:用于一次性定时任务。

  • time.Ticker:用于周期性任务。

二、定时器的产生背景

  最原始的问题:程序需要“等待一段时间”

在计算机早期(单线程执行时代),程序的执行是连续的。
但是很多场景需要“延时执行”或“定时触发”:

  • 例如:

    • 网络请求超时控制(5 秒无响应就退出)

    • 每隔一段时间采集一次数据

    • 定时清理缓存或 session

    • 周期性健康检查(health check)

    • 执行计划任务(类似 cron job)

这些任务都需要一种机制:“在未来的某个时间点执行某个动作”

三、Go 定时器的内部实现原理

Go runtime 的定时器系统是由调度器(scheduler)管理的。
主要基于 最小堆(min-heap)结构

思想:

  • 所有活跃的 TimerTicker 都存储在一个堆中;

  • 堆顶是下一个即将触发的定时器

  • runtime 中有一个专门的 goroutine(叫 timerproc)循环运行:

    • 检查堆顶的到期时间;

    • 睡眠到该时间;

    • 时间一到,就唤醒并执行对应的回调或发送信号。

伪代码示意:

for {t := heap.Top() // 最近的定时器sleepUntil(t.when)trigger(t) // 执行任务}

这种机制的好处:

  • 所有定时任务集中管理;

  • 效率极高(对堆的操作,O(log n) 插入、O(1) 取最早任务);

四、time.Timer —— 一次性定时器

1. 基本用法

package mainimport ("fmt""time"
)func main() {timer := time.NewTimer(2 * time.Second)fmt.Println("等待中...")<-timer.C // 阻塞,直到2秒后收到信号fmt.Println("2秒到了!")
}

解释:

  • time.NewTimer(d) 创建一个定时器;

  • timer.C 是一个只读 channel;

  • 当时间到达后,系统会向 timer.C 发送一个时间值;

  • <-timer.C 会阻塞直到时间到。

2. 另一种方式:time.After

time.After 是一个简化版本,会在指定时间后返回一个 channel:

<-time.After(3 * time.Second) fmt.Println("3秒到了!")

这其实相当于:

timer := time.NewTimer(3 * time.Second) <-timer.C

适合简单一次性延迟的场景。

3.取消定时器:Stop()

如果不再需要一个定时器(例如提前退出、释放资源),应该调用:

timer := time.NewTimer(5 * time.Second)
go func() {<-timer.Cfmt.Println("定时任务执行")
}()time.Sleep(2 * time.Second)
if timer.Stop() {fmt.Println("定时器被取消")
}

 注意:如果定时器已经触发(channel 已经有值),Stop() 会返回 false

4.重置定时器:Reset()

如果想复用一个定时器:

timer := time.NewTimer(2 * time.Second)
<-timer.C // 第一次触发timer.Reset(1 * time.Second) // 重新开始计时
<-timer.C
fmt.Println("又过了1秒")

五、time.Ticker —— 周期性定时器

1.开启定时器。

ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()for t := range ticker.C {fmt.Println("时间到了:", t)
}

每隔 1 秒,ticker.C 就会收到一个时间值。

2.停止定时器

必须手动调用:

ticker.Stop()

否则 goroutine 不会结束,可能导致内存泄漏。

六、定时器案例

1.用timer模拟闹钟贪睡

package mainimport ("fmt""time"
)func main() {// 闹钟,自动重试任务// NewTimer 创建一个 Timer,它会在最少过去时间段 d 后到期,向其自身的 C 字段发送当时的时间timer1 := time.NewTimer(5 * time.Second)fmt.Println("开始时间:", time.Now().Format("2006-01-02 15:04:05"))go func(t *time.Timer) {times := 0for {<-t.Cfmt.Println("timer", time.Now().Format("2006-01-02 15:04:05"))// 从t.C中获取数据,此时time.Timer定时器结束。如果想再次调用定时器,只能通过调用 Reset() 函数来执行// Reset 使 t 重新开始计时,(本方法返回后再)等待时间段 d 过去后到期。// 如果调用时 t 还在等待中会返回真;如果 t已经到期或者被停止了会返回假。times++// 调用 reset 重发数据到chan Cfmt.Println("调用 reset 重新设置一次timer定时器,并将时间修改为2秒")t.Reset(2 * time.Second)if times > 3 {fmt.Println("调用 stop 停止定时器")t.Stop()}}}(timer1)time.Sleep(30 * time.Second)fmt.Println("结束时间:", time.Now().Format("2006-01-02 15:04:05"))fmt.Println("ok")
}

2.用ticker模拟心跳检测

package mainimport ("fmt""time"
)func main() {ticker := time.NewTicker(2 * time.Second)defer ticker.Stop() // 函数结束时关闭 tickerdone := make(chan bool)// 模拟外部协程:10秒后关闭心跳go func() {time.Sleep(10 * time.Second)done <- true}()for {select {case t := <-ticker.C:fmt.Println("发送心跳包:", t)case <-done:fmt.Println("停止发送心跳包")return}}
}

我们可以通过以上案例看到,timer定时器和reset函数组合,也可以达到ticker的效果。

七、总结

对比

  • Timer:一次性触发,适合延迟任务或超时控制。

  • Ticker:周期性触发,适合重复任务。

选择场景

  • Timer:如 HTTP 请求超时、延迟执行任务。

  • Ticker:如定时刷新数据、心跳检测。

注意事项

  • Ticker 如果不停止,会持续运行,可能导致资源泄露。始终记得在不需要时调用 Stop()。

  • Timer 触发后会自动失效,无需担心资源问题。

http://www.dtcms.com/a/504101.html

相关文章:

  • 【NVIDIA显卡驱动和GPU管理工具—nvidia-driver 和 nvidia-smi 简介】
  • 学校网站建设目的WordPress浮动导航插件
  • 快速上手大模型:机器学习4
  • 短波红外相机的简单介绍和场景应用
  • Python图形化界面——pyqt5教程
  • 人和兽做的网站视频学动漫设计去哪个学校
  • 东莞响应式网站建设定制石家庄造价工程信息网
  • 榆林网站建设公司12306的网站是哪个公司做的
  • PCIe协议之 Equalization篇 之 如何重新发起 EQ?
  • 贵阳网站建设我国网络营销现状分析
  • FPGA的时钟输入和JESD204B 接口对时钟的要求
  • 佛山多语网站制作公司网站官网
  • 企业官网的应用场景视频网站seo怎么做
  • 济南企业建设网站网页制作好了如果让别人搜到
  • Java零基础入门:面向对象讲解 --- OOP(上)
  • python | requests爬虫如何正确获取网页编码?
  • C语言对单链表的操作
  • DeepLab系列算法介绍
  • apache设置网站网址怎样将ftp转换为wordpress
  • .net和php哪个做网站好红色简约的手机社区类网站html5响应式模板下载
  • 民兵信息化网站建设wordpress页面添加照片
  • Docker 安装 CentOS
  • 做黑彩票的网站赚钱吗微信公众号怎么做好看
  • 内蒙古集宁建设厅官方网站国外app设计网站
  • C++ vector类的使用
  • 咸阳建设局网站自己公司怎样弄个网站
  • 网站做推广需要什么条件免费制作招聘的app
  • 临沂市建设安全管理网站nginx 搭建wordpress
  • 管理有限公司网站设计中文企业网站html模板
  • 网站的搜索功能怎么做网站建设实训报告模板