促使我写这篇文章主要是在写一个关于虚拟货币账户监控的项目时使用 Ticker 的问题。
Ticker 的问题
如果用过 Ticker 的朋友会知道,创建 Ticker 后并不会马上执行,而是会等待一个时间 d
,这就是创建时的间隔时间。如果间隔时间很短这基本上不会有太大问题,但是如果对首次执行时间有要求,就会很麻烦。例如以下这个案例:
package main
import (
"fmt"
"sync"
"time"
)
func main() {
ts := time.NewTicker(5 * time.Second)
fmt.Println("start_time#", time.Now().Unix())
chanClose := make(chan struct{})
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
for {
select {
case
它将返回以下内容:
start_time# 1656860176
run_time# 1656860181
run_time# 1656860186
为了方便演示我们在事例中设了一个很短的时间,我们可以看到从代码启动到真正定时器触发,代码等待了5秒,就是 time.NewTicker
创建时我们传的参数时间。但如果我们把这个时间改成1个小时,我们需要等待1个小时才会真正开始执行。
寻找解决方案
package main
import (
"fmt"
"sync"
"time"
)
func main() {
ts := time.NewTicker(5 * time.Second)
fmt.Println("start_time#", time.Now().Unix())
var wg sync.WaitGroup
wg.Add(1)
go func() {
for ; true;
上述的执行后返回内容:
start_time# 1656860889
run_time# 1656860889
run_time# 1656860894
我们可以看到首次定时器触发任务的时间变成了程序执行的开始时间!在我们的例子中,这种方式没有问题,但是我们需要关注退出条件,在这里是 main goroutine 直接退出。第一个 goroutine 其实直到 main 退出前一直是堵塞状态。如果你的项目中多次使用这种形式的定时器,每一个都会有一个堵塞的 goroutine,虽然不会对你程序造成 panic,但我还是感觉不是很好。
我的版本
先上代码:
package ticktock
import (
"time"
)
// 这个结构体内容是为了兼容 Ticker 的使用方式
type tickerStart struct {
C chan time.Time
ticker *time.Ticker
close chan struct{}
}
func NewTickerStart(d time.Duration) *tickerStart {
// 这里我们创建的 channel 设了一个 buffer,原因是我们需要
// 在下面 Start 方法中及时推送当前时间而不至于堵塞。
//
c := make(chan time.Time, 1)
return &tickerStart{ticker: time.NewTicker(d), C: c, close: make(chan struct{})}
}
// 这是我们核心的方法
func (ts *tickerStart) Start() {
ts.C
使用代码如下:
package main
import (
"fmt"
"sync"
"time"
"ticktock"
)
func main() {
fmt.Println("start_time#", time.Now().Unix())
chanClose := make(chan struct{})
tts := ticktock.NewTickerStart(5 * time.Second)
tts.Start()
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
for {
select {
case
执行返回内容如下:
start_time# 1656861872
run_time# 1656861872
run_time# 1656861877
可以看到,和我们想要的一致。但和官方给出的不同我们不会堵塞 goroutine 。
这是我在写虚拟货币账户监控项目中碰到的其中一个问题,我也会在后续的文章中写一写我碰到的其他问题。当然这个项目会开源,可以关注我的 github GanymedeNil’s github。
最后的最后
Original: https://www.cnblogs.com/canyuexiang/p/16441444.html
Author: GanymedeNil
Title: 支持首次触发的 Go Ticker
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/516265/
转载文章受原作者版权保护。转载请注明原作者出处!