go context包的WithTimeout和WithCancel的使用
2024-09-27 09:10:14
1、WaitGroup
它是一种控制并发的方式,它的这种方式是控制多个goroutine同时完成。
func main() {
var wg sync.WaitGroup
wg.Add(2)
go func() {
time.Sleep(2*time.Second)
fmt.Println("1号完成")
wg.Done()
}()
go func() {
time.Sleep(2*time.Second)
fmt.Println("2号完成")
wg.Done()
}()
wg.Wait()
fmt.Println("好了,大家都干完了,放工")
}
一个很简单的例子,一定要例子中的2个goroutine同时做完,才算是完成,先做好的就要等着其他未完成的,所有的goroutine要都全部完成才可以。
2、chan通知
我们都知道一个goroutine启动后,我们是无法控制他的,大部分情况是等待它自己结束,那么如果这个goroutine是一个不会自己结束的后台goroutine呢?比如监控等,会一直运行的。
这种情况化,一直傻瓜式的办法是全局变量,其他地方通过修改这个变量完成结束通知,然后后台goroutine不停的检查这个变量,如果发现被通知关闭了,就自我结束。
这种方式也可以,但是首先我们要保证这个变量在多线程下的安全,基于此,有一种更好的方式:chan + select 。
func main() {
stop := make(chan bool)
go func() {
for {
select {
case <-stop:
fmt.Println("监控退出,停止了...")
return
default:
fmt.Println("goroutine监控中...")
time.Sleep(2 * time.Second)
}
}
}()
time.Sleep(10 * time.Second)
fmt.Println("可以了,通知监控停止")
stop<- true
//为了检测监控过是否停止,如果没有监控输出,就表示停止了
time.Sleep(5 * time.Second)
}
3、WithTimeout 超时自动取消方法
当执行一个go 协程时,超时自动取消协程
// 模拟一个最小执行时间的阻塞函数
func inc(a int) int {
res := a + 1 // 虽然我只做了一次简单的 +1 的运算,
time.Sleep(1 * time.Second) // 但是由于我的机器指令集中没有这条指令,
// 所以在我执行了 1000000000 条机器指令, 续了 1s 之后, 我才终于得到结果。B)
return res
} // 向外部提供的阻塞接口
// 计算 a + b, 注意 a, b 均不能为负
// 如果计算被中断, 则返回 -1
func Add(ctx context.Context, a, b int) int {
res := 0
for i := 0; i < a; i++ {
res = inc(res)
select {
case <-ctx.Done():
return -1
default:
}
}
for i := 0; i < b; i++ {
res = inc(res)
select {
case <-ctx.Done():
return -1
default:
}
}
return res
}
计算 a+b
func main() {
// 使用开放的 API 计算 a+b
a := 1
b := 2
timeout := 2 * time.Second
ctx, _ := context.WithTimeout(context.Background(), timeout)
res := Add(ctx, 1, 2)
fmt.Printf("Compute: %d+%d, result: %d\n", a, b, res)
}
输出结果:Compute: 1+2, result: -1
4、WithCancel 手动取消方法
func main() {
// 手动取消
a := 1
b := 2
ctx, cancel := context.WithCancel(context.Background())
go func() {
time.Sleep(2 * time.Second)
cancel() // 在调用处主动取消
}()
res := Add(ctx, 1, 2)
fmt.Printf("Compute: %d+%d, result: %d\n", a, b, res)
}
输出结果:Compute: 1+2, result: -1
最新文章
- Tiff – 值得你体验一下的可视化的字体对比工具
- LeetCode Single Number III
- .NET类型转换的常用方式
- vim 文字插入
- POJ2739 - Sum of Consecutive Prime Numbers(素数问题)
- 微信.NET 微信开发 自己主动内容回复 ASP.NET C#代码
- 使用ASP.NET实现Windows Service定时执行任务
- LightOJ_1038 Race to 1 Again
- bzoj 3594: [Scoi2014]方伯伯的玉米田 dp树状数组优化
- android——ObjectAnimator动画
- 2014年2月5日 Oracle ORACLE的工作机制[转]
- Reactive ExtensionsLINQ和Rx简单介绍
- C# 语言规范_版本5.0 (第8章 语句)
- Python的Web应用框架--Django
- CSS 设置table下tbody滚动条
- 洛谷 P1101 单词方阵
- Centos如何安装163yum源
- Alpha冲刺 - (10/10)
- 记录Ubuntu 16.04 安装Docker CE
- Git 获取仓库(分布式版本控制系统)
热门文章
- http://my.oschina.net/China2012/blog/178655
- SQL通过身份证获取信息
- Oracle数据迁移至HBase操作记录
- 常用class 总结
- Unity5.1 新的网络引擎UNET(九) UNET 官方推荐视频教程
- vue - webpack.prod.conf.js
- 《Java程序猿面试笔试宝典》之 什么是AOP
- cookie、localStorage和sessionStorage区别
- Android五天乐(第二天)Activity跳转与传输数据,Fragment
- tomcat+nginx+redis集群试验