首页 > 技术文章 > 使用waitgroup在循环中开Goroutine处理并发任务

paulwhw 2020-10-30 21:01 原文

简介

  实际项目中遇到了需要并发处理的任务,在for循环中用Go的Goroutine去处理任务遇到了一些问题,这里写一个demo记录一下简单的过程。

同步的代码

  这里用一个简单的time.sleep模拟一下同步的代码,然后再看看开协程处理的不同之处:

package main

import (
    "fmt"
    "time"
)

func main() {

    // 同步代码
    lst := []int8{1,2,3}
    start := time.Now()
    for _,i := range lst{
        DeltaTask(i)
    }
    end := time.Now()
    ret := end.Sub(start)
    fmt.Printf("耗时:%v",ret)
}

// 模仿耗时的任务
func DeltaTask(i int8){
    time.Sleep(time.Duration(i)*time.Second)
}

// 耗时:6.008863168s

开协裎的写法

  这里直接上代码:

package main

import (
    "fmt"
    "sync"
    "time"
)

func main() {

    // 异步代码
    lst := []int8{1,2,3}
    start := time.Now()
    // 定义一个waitgroup
    wait := sync.WaitGroup{}
    for _,i := range lst{
        // tag +1
        wait.Add(1)
        // go一个匿名函数
        go func(delta int8){
            // tag -1
            defer wait.Done()
            DeltaTask(delta)
        }(i)
    }
    // 主线程等待 "计时器" 为0才往下走直到停止
    wait.Wait()
    end := time.Now()
    ret := end.Sub(start)
    fmt.Printf("耗时:%v",ret)
}

// 模仿耗时的任务
func DeltaTask(i int8){
    time.Sleep(time.Duration(i)*time.Second)
}
// 耗时:3.005254124s

  这里最重要的就是WaitGroup的使用!可以跟Python并发编程中的join方法进行类比:因为在Go中主线程结束后意味着主线程中开的协裎也都挂了,所以一定要确保执行协裎任务时主线程一直处于wait的状态!

推荐阅读