golang 中的 time 包的 Ticker
2024-10-19 02:54:49
真实的应用场景是:在测试收包的顺序的时候,加了个 tick 就发现丢包了
那么来看一个应用例子:
package main import (
"fmt"
"runtime"
"time"
) func init() {
runtime.GOMAXPROCS(runtime.NumCPU())
} func main() {
ch := make(chan int, )
go func(ch chan int) {
for {
val := <-ch
fmt.Printf("val:%d\n", val)
}
}(ch) tick := time.NewTicker( * time.Second)
for i := ; i < ; i++ {
select {
case ch <- i:
case <-tick.C:
fmt.Printf("%d: case <-tick.C\n", i)
} time.Sleep( * time.Millisecond)
}
close(ch)
tick.Stop()
}
输出结果如下:
val:0
val:1
val:2
val:3
val:4
val:5
6: case <-tick.C
val:7
val:8
val:9
10: case <-tick.C
val:11
val:12
val:13
val:14
15: case <-tick.C
val:16
val:17
val:18
val:19
问题出在这个select里面:
select {
case ch <- i:
case <-tick.C:
fmt.Printf("%d: case <-tick.C\n", i)
}
[tick.C 介绍说明]当两个 case 条件都满足的时候,运行时系统会通过一个伪随机的算法决定哪个case将会被执行。所以当 tick.C 条件满足的那个循环,有某种概率造成 ch<-i 没有发送(虽然通道两端没有阻塞,满足发送条件)
解决方案1:一旦 tick.C 随机的 case 被随机到,就多执行一次 ch<-i (不体面,如果有多个case就不通用了)
select {
case ch <- i:
case <-tick.C:
fmt.Printf("%d: case <-tick.C\n", i)
ch <- i
}
解决方案2:将tick.C的case单独放到一个select里面,并加入一个default(保证不阻塞)
select {
case ch <- i:
}
select {
case <-tick.C:
fmt.Printf("%d: case <-tick.C\n", i)
default:
}
两种解决方案的输出都是希望的结果:
val:
val:
val:
val:
val:
: case <-tick.C
val:
val:
val:
val:
val:
: case <-tick.C
val:
val:
val:
val:
val:
: case <-tick.C
val:
val:
val:
val:
val:
最新文章
- 软件工程导论-目录-K-T+RJ大
- Mybatis框架基于注解的方式,实对数据现增删改查
- DBUTIL 调用存储过程例子
- a标签不跳转
- Swift数据类型简介(二)
- 向Windows 日志管理器写入系统程序日志信息
- 【剑指offer】和为定值的连续正数序列
- SQLite存储区的日志模式
- mysql语句优化总结(一)
- php错误 分析
- 【leetcode】经典算法题-Counting Bits
- Qt窗口定制
- c/c++ 拷贝控制 构造函数的问题
- P2146 [NOI2015]软件包管理器
- HDU5293 : Tree chain problem
- Jquery闪烁提示特效
- Spring MVC 源码分析
- Redis进阶之redis的生命周期
- windows下安装python3 新手上路
- PyQt5--MenuBar