go语言的单次定时器通道NewTimer()

func NewTimer

func NewTimer(d Duration) *Timer

NewTimer创建一个Timer,它会在最少过去时间段d后到期,向其自身的C字段发送当时的时间。

Timer是一次性的时间触发事件

虽然往通道写入数据了,但是后面不会堵塞,因为是内部开辟协程写入,不取从通道时间不堵塞,取时间就会堵塞

对于NewTimer和After这两种创建方法,则是Timer在超时(timer expire)后,执行一个标准库中内置的函数:sendTime。sendTime将当前当前事件send到timer的时间Channel中,那么说这个动作不会阻塞到timerproc的执行么?答案肯定是不会的,其原因就在下面代码中:

//$GOROOT/src/time/sleep.go
func NewTimer(d Duration) *Timer {
    c := make(chan Time, 1)
    t := &Timer{
        C: c,
        ... ...
    }
    ... ...
    return t
}

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:
    }
}

我们看到NewTimer中创建了一个buffered channel,size = 1。正常情况下,当timer expire,t.C无论是否有goroutine在read,sendTime都可以non-block的将当前时间发送到C中;同时,我们看到sendTime还加了双保险:通过一个select判断c buffer是否已满,一旦满了,直接退出,依然不会block,这种情况在reuse active timer时可能会遇到。

package main

import (
	"fmt"
	"time"
)

func main() {
	timer := time.NewTimer(time.Duration(5) * time.Second)
	fmt.Println(time.Now())
	//NewTimer不会堵塞当前的
	for {
		fmt.Println(<-timer.C)
		timer.Reset(2 * time.Second)
	}

	//timer = time.NewTimer(time.Duration(2) * time.Second)
	//select {
	//case <-timer.C:
	//	fmt.Println("执行...")
}

//---------------------------------------------------------------
2018-12-28 14:50:57.4505215 +0800 CST m=+0.005985001
2018-12-28 14:51:02.4512457 +0800 CST m=+5.006724301
2018-12-28 14:51:04.4515802 +0800 CST m=+7.007064901
2018-12-28 14:51:06.4519336 +0800 CST m=+9.007424301
2018-12-28 14:51:08.4523644 +0800 CST m=+11.007861201
2018-12-28 14:51:10.452537 +0800 CST m=+13.008039801

第一次取数据的时候单次定时器是5S , 等对定时器复位后则 , 定时器复位并定时为2S

time.After()返回只读channel

package main

import (
	"fmt"
	"time"
)

func main() {
	ch := make(chan string)
	go func() {
		time.Sleep(time.Second * 2)
		ch <- "result"
	}()
	select {
	case res := <-ch:
		fmt.Println(res)
	case <-time.After(time.Second * 1):
		/*
		func After(d Duration) <-chan Time {
	    return NewTimer(d).C
        }
		返回值为只读channel
		*/
		//只读channel,只写channel
		fmt.Println("timeout")
	}
}
/*
Go中channel可以是只读、只写、同时可读写的。

//定义只读的channel

read_only := make (<-chan int)



//定义只写的channel

write_only := make (chan<- int)



//可同时读写

read_write := make (chan int)*/

猜你喜欢

转载自blog.csdn.net/weixin_42544051/article/details/85321792