• Go中的工作池:并发任务的优雅管理


    一、前言

    在当今的软件开发领域,处理大规模并发任务是一项关键挑战。Go语言以其强大的并发支持而闻名,而工作池是一种在Go中管理并发任务的精巧方式。本文将介绍工作池的工作原理,并通过代码示例演示其在实际应用中的用途。

    二、内容

    2.1 什么是工作池?

    工作池是一种并发编程模式,它使用一组固定数量的工作线程来执行任务队列中的工作单元。这有助于控制并发,避免资源竞争,并允许更好地利用计算资源。在Go中,工作池通常使用 goroutines 和通道来实现。

    2.2 实现一个简单的工作池

    我们将从一个简单的示例开始,以便更好地理解工作池的概念。假设我们有一组耗时的任务需要执行,我们希望并行执行它们,但同时限制并发度。

    package main
    
    import (
        "fmt"
        "time"
    )
    
    func worker(id int, jobs <-chan int, results chan<- int) {
        for j := range jobs {
            fmt.Println("Worker", id, "processing job", j)
            time.Sleep(time.Second)
            results <- j * 2
        }
    }
    
    func main() {
        jobs := make(chan int, 100)
        results := make(chan int, 100)
    
        // 启动3个worker
        for w := 1; w <= 3; w++ {
            go worker(w, jobs, results)
        }
    
        // 发送9个任务到队列
        for j := 1; j <= 9; j++ {
            jobs <- j
        }
        close(jobs)
    
        // 收集所有任务的结果
        for a := 1; a <= 9; a++ {
            <-results
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    执行上述代码,您会看到9个任务被多个worker并行执行。整个程序的执行时间仅为3秒,而不是9秒,这是因为3个worker同时工作。

    2.3 工作池的应用场景

    工作池在许多应用中都非常有用,下面我们将探讨一些实际场景。

    (一) 网络请求并行化

    假设您需要从多个远程API获取数据,而每个请求都需要一定的时间。使用工作池,您可以并行执行这些请求,提高数据获取的效率。

    package main
    
    import (
        "fmt"
        "net/http"
        "sync"
    )
    
    func fetchURL(url string, wg *sync.WaitGroup) {
        defer wg.Done()
        resp, err := http.Get(url)
        if err != nil {
            fmt.Println("Error fetching", url, ":", err)
            return
        }
        defer resp.Body.Close()
        fmt.Println("Fetched", url)
        // 处理响应
    }
    
    func main() {
        urls := []string{"http://example.com", "http://google.com", "http://github.com"}
        var wg sync.WaitGroup
    
        // 创建工作池并启动多个worker
        workerCount := 3
        jobs := make(chan string, len(urls))
        for i := 0; i < workerCount; i++ {
            go func() {
                for url := range jobs {
                    fetchURL(url, &wg)
                }
            }()
        }
    
        // 分发任务
        for _, url := range urls {
            wg.Add(1)
            jobs <- url
        }
    
        close(jobs)
        wg.Wait()
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    (二) 批量处理数据

    工作池还可以用于批量处理数据,例如批量转换图像、处理大量文本文件等。这样可以将处理任务分发到多个worker以加快处理速度。

    package main
    
    import (
        "fmt"
        "io/ioutil"
        "os"
        "sync"
    )
    
    func processFile(filename string, wg *sync.WaitGroup) {
        defer wg.Done()
        // 处理文件逻辑
        fmt.Println("Processing file:", filename)
    }
    
    func main() {
        files, err := ioutil.ReadDir("/path/to/files")
        if err != nil {
            fmt.Println("Error reading directory:", err)
            return
        }
    
        var wg sync.WaitGroup
        workerCount := 4
        jobs := make(chan string, len(files))
    
        // 启动工作池
        for i := 0; i < workerCount; i++ {
            go func() {
                for file := range jobs {
                    processFile(file, &wg)
                }
            }()
        }
    
        // 分发任务
        for _, file := range files {
            wg.Add(1)
            jobs <- file.Name()
        }
    
        close(jobs)
        wg.Wait()
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    三、总结

    工作池是Go中强大的并发编程工具,可用于有效管理并行任务。它有助于限制并发度、避免资源竞争和提高计算资源的利用率。通过这个教程,您学会了如何创建和使用工作池,并了解了它的一些应用场景。

  • 相关阅读:
    c++中的左值引用和右值引用
    前端基础入门之JS对象 原型 prototype
    大模型系统和应用——神经网络基础
    C++ 类的继承(Inheritance)
    JavaScript正则表达式加密
    Java笔记:JVM参数调优
    Unreal PythonScriptPlugin
    electron-log使用
    面试官:说说SSO单点登录的实现原理?
    Linux之并发竞争管理
  • 原文地址:https://blog.csdn.net/m0_73728511/article/details/133915355