Go之定时器的使用

一、背景介绍

笔者最近在使用Go的定时器,发现Go提供的time包里面,按照下面几种场景做了区分,并分别提供一些API支持。主要场景如下所示:

1.超时一次之后,就不再使用的定时器,time.After()。2.每隔一段时间,就需要使用一次的定时器,time.Tick()。3.阻塞住goroutinue的定时器,time.Sleep(),准确来说这个不算一个定时器4.可以自由控制定时器启动和关闭的定时器,time.Ticker()。

二、实例演练

1. time.After()

调用time.After(duration),此函数马上返回,返回一个time.Time类型的Chan,不阻塞。后面你该做什么做什么,不影响。到了duration时间后,自动塞一个当前时间进去,底层是用NewTimer实现的。

参考:
https://golang.org/pkg/time/#After

func After(d Duration) <-chan Time

After waits for the duration to elapse and then sends the current time on the returned channel. It is equivalent to NewTimer(d).C. The underlying Timer is not recovered by the garbage collector until the timer fires. If efficiency is a concern, use NewTimer instead and call Timer.Stop if the timer is no longer needed.

例子:

代码:package mainimport ( 'fmt' 'time')func main() { tchan := time.After(time.Second * 3) fmt.Println(time.Now().String(),'tchan type:%T', tchan) fmt.Println(time.Now().String(),'mark 1') fmt.Println(time.Now().String(),'tchan=', <-tchan) // channel里取出数据之后,会发现超时间是3秒 fmt.Println(time.Now().String(),'mark 2')}输出结果:2009-11-10 23:00:00 +0000 UTC m=+0.000000001 tchan type:%T 0xc0001041202009-11-10 23:00:00 +0000 UTC m=+0.000000001 mark 12009-11-10 23:00:00 +0000 UTC m=+0.000000001 tchan= 2009-11-10 23:00:03 +0000 UTC m=+3.0000000012009-11-10 23:00:03 +0000 UTC m=+3.000000001 mark 2

场景讲解:

使用了time.After之后,只有在调用了<-tchan之后,才会真正的触发超时的操作,在此之前的代码是可以被立马执行的,因为time.After不会阻塞当前的goroutine。

2. time.Tick()

Tick函数是使用channel阻塞当前协程,完成定时任务的执行,用来处理间隔一段固定时间来处理一部分事情的。原文如下:
https://golang.org/pkg/time/#Tick

func Tick(d Duration) <-chan Time

Tick is a convenience wrapper for NewTicker providing access to the ticking channel only. While Tick is useful for clients that have no need to shut down the Ticker, be aware that without a way to shut it down the underlying Ticker cannot be recovered by the garbage collector; it 'leaks'. Unlike NewTicker, Tick will return nil if d <= 0.

例子:

代码:package mainimport ( 'fmt' 'time')func main() { c := time.Tick(2 * time.Second)  for next := range c {   fmt.Printf('%v \n', next)   }}结果输出:timeout running program2009-11-10 23:00:02 +0000 UTC m=+2.000000001 2009-11-10 23:00:04 +0000 UTC m=+4.000000001 2009-11-10 23:00:06 +0000 UTC m=+6.000000001 2009-11-10 23:00:08 +0000 UTC m=+8.000000001

场景讲解:

这段代码是希望每次间隔2秒钟执行一次打印操作,备注:对于Tick来说,返回的是一个只读channel,这里的channel不要使用者做额外的操作,只需要使用就可以,因为这个Tick针对的场景就是那种不需要关闭时间的场景。

3. time.Sleep()

Sleep是使用睡眠完成定时,结束后继续往下执行循环来实现定时任务,Sleep的过程中是会阻塞当前goroutinue的。原文参考:
https://golang.org/pkg/time/#Sleep

func Sleep(d Duration)

Sleep pauses the current goroutine for at least the duration d. A negative or zero duration causes Sleep to return immediately.

例子:

代码:package mainimport ( 'fmt' 'time')func main() { for {   fmt.Printf('start %v \n', time.Now()) time.Sleep(2 * time.Second) // time.Sleep的过程中,下面的打印不会执行   fmt.Printf('end %v \n', time.Now())   }}结果输出:timeout running programstart 2009-11-10 23:00:00 +0000 UTC m=+0.000000001 end 2009-11-10 23:00:02 +0000 UTC m=+2.000000001 start 2009-11-10 23:00:02 +0000 UTC m=+2.000000001 end 2009-11-10 23:00:04 +0000 UTC m=+4.000000001 start 2009-11-10 23:00:04 +0000 UTC m=+4.000000001 end 2009-11-10 23:00:06 +0000 UTC m=+6.000000001 start 2009-11-10 23:00:06 +0000 UTC m=+6.000000001 end 2009-11-10 23:00:08 +0000 UTC m=+8.000000001 .......

场景讲解:

从执行的打印来看,Sleep被调用之后,当前的goroutine是被阻塞住的,只有Sleep的时间到了之后,才会继续执行后续的操作。

4.time.Ticker

Ticker 和 Timer 类似,区别是:Ticker 中的 runtimeTimer 字段的 period 字段会赋值为 NewTicker(d Duration) 中的 d,表示每间隔 d 纳秒,定时器就会触发一次。

除非程序终止前定时器一直需要触发,否则,不需要时应该调用 Ticker.Stop 来释放相关资源。

原文参考如下:
https://golang.org/pkg/time/#Ticker

例子:

代码:package mainimport (  'fmt'  'time')func main() {  ticker := time.NewTicker(time.Second)    defer ticker.Stop()    done := make(chan bool)    go func() {        time.Sleep(5 * time.Second) // 5s后触发time.Stop,关闭ticker        done <- true    }()    for {            select {           case <-done:              fmt.Println('Done!')              return            case t := <-ticker.C:             fmt.Println('Current time: ', t)         }    }}执行结果:Current time:  2009-11-10 23:00:01 +0000 UTC m=+1.000000001Current time:  2009-11-10 23:00:02 +0000 UTC m=+2.000000001Current time:  2009-11-10 23:00:03 +0000 UTC m=+3.000000001Current time:  2009-11-10 23:00:04 +0000 UTC m=+4.000000001Current time:  2009-11-10 23:00:05 +0000 UTC m=+5.000000001Done!

场景讲解:希望每隔1s执行一次打印操作,等待5s之后,终止这个操作。通过上面的输出我们能够看出来,time.Stop在调用了之后,timer便不再继续执行了。

(0)

相关推荐

  • 回答我,停止 Goroutine 有几种方法?

    大家好,我是煎鱼. 协程(goroutine)作为 Go 语言的扛把子,经常在各种 Go 工程项目中频繁露面,甚至有人会为了用 goroutine 而强行用他. 在 Go 工程师的面试中,也绕不开他, ...

  • Go程是如何创建和何时销毁的?

    Go程如何创建? 通过go关键字进行创建,看一下代码,很简单: go test(j) // test是一个函数 Go程如何销毁,何时销毁? 创建一个Go程简单,但何时销毁呢?这个问题稍微有点复杂,看个 ...

  • PHP没有定时器?

    PHP没有定时器? 确实,PHP没有类似于JS中的setInterval或者setTimeout这样的原生定时器相关的函数.但是我们可以通过其他方式来实现,比如使用declare. 先来看看是如何实现 ...

  • python threads,threading的用法

    python threads,threading的用法

  • go协程全局变量和局部变量

    原文链接:http://www.zhoubotong.site/post/19.html 大家可能经常会用到类似如下代码片段: package main import ( "fmt" ...

  • Python学习—装饰器

    学习Python已经有一段时间了,陆续学了一些基础部分,但是理解的不是很深刻,每过一段时间就会忘记,所以不得不写一些博客进行记录,加深自己的理解.这两个星期一直在研究装饰器,开始觉得很简单,但是只知其 ...

  • 4412开发板Qt定时器-实验步骤和部分代码

    实验目标:实现计时器功能,并且点击打点按钮将当前时间打印出来. 用到的类有 QTimer 和 QTime,QTimer 是一个计时器类,相当于秒表,QTimer 是一个时间类,相当于手表. 一:实验步 ...

  • 如何在Excel里使用定时器

    用过 Excel 97 里的加载宏 "定时保存" 吗?可惜它的源程序是加密的,现在就上传一篇介绍实现它的文档. 在 Office 里有个方法是 application.ontime ...

  • 在PLC编程中定时器的一些针对现场不同情况的一些妙用

    相信大家在PLC编程中常会用到定时器,定时器指令也是比较常用的指令,一般分为接通延时定时器.断开延时定时器.脉冲定时器等,相信大家对于指令也已经很熟悉,在本文中就不具体介绍定时器指令了. 本文重点介绍 ...

  • 关于定时器Scheduled(cron)的问题

    定时器配置步骤参考:http://blog.csdn.NET/sd4000784/article/details/7745947 下面给出cron参数中各个参数的含义: CRON表达式    含义  ...

  • 西门子博途中的定时器指令

    S7-1200的定时器为IEC定时器,用户程序中可以使用的定时器数量仅受CPU的存储器容量限制.      使用定时器需要使用定时器相关的背景数据块或者数据类型为IEC_TIMER(或TP_TIME. ...

  • 「公牛小课堂」电子式定时器操作篇

    日常生活中,有些电器并不需要24小时通电,例如空调.热水器.鱼缸氧气泵和电瓶充电等,时间的不可控会给我们的休息带来一些不便利因素.借助定时器对这些电器进行定时开关,不仅更加省事而且还能起到更好的节能效 ...

  • 【新提醒】由与非门构成的555定时器触发锁存电路,不看肯定后悔

    0 当工作在单稳态时,包括NE/SE555在内的商用集成定时器的应用有很多限制.这是因为它们不能在任一种触发脉冲条件下都可正常工作.只要输入脉冲小于设定时间周期,这些定时器就能很好工作并产生准确输出. ...

  • 基于555定时器的电动机无触点开关控制电路

    本文是基于555定时器双稳态触发电路和双向晶闸管组成的电动机无触点开关控制电路,利用双稳态触发电路输出的两种稳定状态(高电平和低电平),通过继电器控制双向晶闸管的通断,实现电动机的启动.停止控制和断相 ...

  • 41个555定时器项目电路原理图

    3*3*3光立方 警报器 闪光器 鸣笛警报器 闪烁电路 闪烁电路 激光射线 闩 电子骰子 LED调光器 555放大器 光检测器 机器枪 金属探测器 电机脉宽调制 LED闪光电路 音乐盒 玩具器官 警灯 ...

  • 定时器_在.net core3.0 webapi中添加自定义定时器功能

    前言:想在.net framework环境使用自定义定时器的话,参考我的另一篇文章:https://www.cnblogs.com/lxhbky/p/10242839.html 想在.net core ...