Goroutine的使用

设置goroutine运行的CPU数量,最新版本的go已经默认已经设置了。

  1. num := runtime.NumCPU() //获取主机的逻辑CPU个数
  2. runtime.GOMAXPROCS(num) //设置可同时执行的最大CPU数

应用示例:

  1. package main
  2. import (
  3. "fmt"
  4. "time"
  5. )
  6. func count(a int , b int ) {
  7. c := a+b
  8. fmt.Printf("%d + %d = %d\n",a,b,c)
  9. }
  10. func main() {
  11. for i :=0 ; i<10 ;i++{
  12. go count(i,i+1) //启动10个goroutine 来计算
  13. }
  14. time.Sleep(time.Second * 3) // sleep作用是为了等待所有任务完成
  15. }

由于goroutine是异步执行的,那很有可能出现主程序退出时还有goroutine没有执行完,此时goroutine也会跟着退出。此时如果想等到所有goroutine任务执行完毕才退出,go提供了sync包和channel来解决同步问题,当然如果你能预测每个goroutine执行的时间,你还可以通过time.Sleep方式等待所有的groutine执行完成以后在退出程序。

  • 使用sync包同步goroutine

sync实现方式是:

WaitGroup 等待一组goroutinue执行完毕. 主程序调用 Add 添加等待的goroutinue数量. 每个goroutinue在执行结束时调用 Done ,此时等待队列数量减1.,主程序通过Wait阻塞,直到等待队列为0.

应用示例:

  1. package main
  2. import (
  3. "fmt"
  4. "sync"
  5. )
  6. func count(a ,b int,n *sync.WaitGroup){
  7. c := a +b
  8. fmt.Printf("The Result of %d + %d=%d\n",a,b,c)
  9. defer n.Done() //goroutinue完成后, WaitGroup的计数-1
  10. }
  11. func main(){
  12. var wg sync.WaitGroup
  13. for i:=0;i<10 ;i++{
  14. wg.Add(1) // WaitGroup的计数加1
  15. go count(i,i+1,&wg)
  16. }
  17. wg.Wait() //等待所有goroutine执行完毕
  18. }

运行

  1. The Result of 9 + 10=19
  2. The Result of 7 + 8=15
  3. The Result of 8 + 9=17
  4. The Result of 5 + 6=11
  5. The Result of 0 + 1=1
  6. The Result of 1 + 2=3
  7. The Result of 2 + 3=5
  8. The Result of 3 + 4=7
  9. The Result of 6 + 7=13
  10. The Result of 4 + 5=9

通过channel实现goroutine之间的同步:

通过channel能在多个groutine之间通讯,当一个goroutine完成时候向channel发送退出信号,等所有goroutine退出时候,利用for循环channe去channel中的信号,若取不到数据会阻塞原理,等待所有goroutine执行完毕,使用该方法有个前提是你已经知道了你启动了多少个goroutine。

  1. package main
  2. import (
  3. "fmt"
  4. "time"
  5. )
  6. func count(a int , b int ,exitChan chan bool) {
  7. c := a+b
  8. fmt.Printf("The Result of %d + %d = %d\n",a,b,c)
  9. time.Sleep(time.Second*2)
  10. exitChan <- true
  11. }
  12. func main() {
  13. exitChan := make(chan bool,10) //声明并分配管道内存
  14. for i :=0 ; i<10 ;i++{
  15. go count(i,i+1,exitChan)
  16. }
  17. for j :=0; j<10; j++{
  18. <- exitChan //取信号数据,如果取不到则会阻塞
  19. }
  20. close(exitChan) // 关闭管道
  21. }

运行:

  1. The Result of 9 + 10 = 19
  2. The Result of 0 + 1 = 1
  3. The Result of 7 + 8 = 15
  4. The Result of 6 + 7 = 13
  5. The Result of 3 + 4 = 7
  6. The Result of 4 + 5 = 9
  7. The Result of 1 + 2 = 3
  8. The Result of 2 + 3 = 5
  9. The Result of 8 + 9 = 17
  10. The Result of 5 + 6 = 11