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



最新文章

  1. Tiff – 值得你体验一下的可视化的字体对比工具
  2. LeetCode Single Number III
  3. .NET类型转换的常用方式
  4. vim 文字插入
  5. POJ2739 - Sum of Consecutive Prime Numbers(素数问题)
  6. 微信.NET 微信开发 自己主动内容回复 ASP.NET C#代码
  7. 使用ASP.NET实现Windows Service定时执行任务
  8. LightOJ_1038 Race to 1 Again
  9. bzoj 3594: [Scoi2014]方伯伯的玉米田 dp树状数组优化
  10. android——ObjectAnimator动画
  11. 2014年2月5日 Oracle ORACLE的工作机制[转]
  12. Reactive ExtensionsLINQ和Rx简单介绍
  13. C# 语言规范_版本5.0 (第8章 语句)
  14. Python的Web应用框架--Django
  15. CSS 设置table下tbody滚动条
  16. 洛谷 P1101 单词方阵
  17. Centos如何安装163yum源
  18. Alpha冲刺 - (10/10)
  19. 记录Ubuntu 16.04 安装Docker CE
  20. Git 获取仓库(分布式版本控制系统)

热门文章

  1. http://my.oschina.net/China2012/blog/178655
  2. SQL通过身份证获取信息
  3. Oracle数据迁移至HBase操作记录
  4. 常用class 总结
  5. Unity5.1 新的网络引擎UNET(九) UNET 官方推荐视频教程
  6. vue - webpack.prod.conf.js
  7. 《Java程序猿面试笔试宝典》之 什么是AOP
  8. cookie、localStorage和sessionStorage区别
  9. Android五天乐(第二天)Activity跳转与传输数据,Fragment
  10. tomcat+nginx+redis集群试验