了解WaitGroups的逻辑

问题描述 投票:-2回答:1

我想了解我围绕WaitGroups的逻辑是否正确,并查看是否有一种更有效的方法来构造我的代码。目的是尽可能快地执行任务。

我的代码填充通过标准输入填充的_urls通道。然后,我将创建两个WaitGroup,一个从该_urls通道读取,另一个从_downloads通道读取,该通道从第一个WaitGroup中的goroutine提供。

基本上,代码看起来像这样:

    // declare channels
    _urls := make(chan string)
    _downloads := make(chan string)

    // first waitgroup with 2 goroutines
    var wg sync.WaitGroup
    for i := 0; i < concurrency; i++ {

        wg.Add(2)

        go func() {
            defer wg.Done()
            for url := range _urls {
                // perform GET request and inspect the responseBody    
            }

        }()

        go func() {
            defer wg.Done()
            for url := range _urls {
                // perform a HEAD request to look for a certain file
                // if the file exists, send to the _downloads channel                
                _downloads <- url
            }
        }()
    }

    // second waitgroup with 1 goroutine
    var dwg sync.WaitGroup
    for i := 0; i < concurrency; i++ {

        dwg.Add(1)

        go func() {
            defer wg.Done()
            for url := range _downloads {
                // perform the download
            }
        }()
    }  

[我担心这是馈送_downloads通道的有效方法,还是仅在第一个WaitGroup中执行下载才有意义?

go concurrency goroutine
1个回答
0
投票

我使用工人池模式https://gobyexample.com/worker-pools进行了类似的操作。如果您希望最大化并发性,那么可能是正确的方向。

它使用go接口抽象作业,因此它可以是HEAD,GET,Do​​wnload或将来发生的其他任何有意义的事情。调度程序将作业发送到管理工作池的调度程序,并将结果发回。

这里是README和代码的链接。

它使用等待组来跟踪活动工人的数量,而不是工作。工人执行for {} loop,仅当他们从已完成的通道中读取为true时,才退出。在这种情况下,使用等待组是为了正常关机。在您的示例中,许多工作人员可能正在长时间下载。因此,您的关闭逻辑可以在关闭之前等待剩余N个作业。

对于您的用例,这可能是过大的。

© www.soinside.com 2019 - 2024. All rights reserved.