golang中timer定时器实现原理

webyh · · 10546 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

一般我们导入import ("time")包,然后调用time.NewTicker(1 * time.Second) 实现一个定时器:

func timer1() {
	timer1 := time.NewTicker(1 * time.Second)
	for {
		select {
		case <-timer1.C:
			xxx() //执行我们想要的操作
		}
	}
}

再看看timer包中NewTicker的具体实现:

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),
			f:      sendTime,
			arg:    c,
		},
	}
	startTimer(&t.r)
	return t
}

其中Ticker的具体struct如下:

type Ticker struct {
	C <-chan Time // The channel on which the ticks are delivered.
	r runtimeTimer
}

Ticker中的C为数据类型为Time的单向管道,只能读,不能写

再分下一下runtimeTimer的参数:

r: runtimeTimer{
			when:   when(d),
			period: int64(d),
			f:      sendTime,
			arg:    c,
		}

其中sendTime为回调函数,startTimer时候注册的,arg为回调函数需要的参数arg

startTimer(&t.r)

再进一步看看startTimer的实现:

func sendTime(c interface{}, seq uintptr) {
	// Non-blocking send of time on c.
	// Used in NewTimer, it cannot block anyway (buffer).
	// Used in NewTicker, dropping sends on the floor is
	// the desired behavior when the reader gets behind,
	// because the sends are periodic.
	select {
	case c.(chan Time) <- Now():
	default:
	}
}

通过往管道里面写时间,注意我们Ticker结构里面的C是单向管道,只能读不能写,那要怎么写数据了

通过类型转化,因为channel是一个原生类型,因此不仅支持被传递,还支持类型转换,装换成双向的管道channel,往里面

写数据,用户API那边提供的是单向管道,用户只能就只能读数据,就相当于一层限制


最后,调用执行具体xxx函数,实现定时执行某些事件的功能:

for {
    select {
	case <-timer1.C:
	  xxxx()
     }
   }



本文来自:开源中国博客

感谢作者:webyh

查看原文:golang中timer定时器实现原理

入群交流(和以上内容无关):加入Go大咖交流群,免费领全套学习资料或添加微信:muxilin131420 备注:入群;或加QQ群:729884609

10546 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传