Golang使用协程池进行 Goroutine 的管理代码示例

协程池是一种常见的协程管理方式,它通过预先创建一定数量的协程,然后将任务放入一个任务队列中,由空闲的协程来执行任务。这样可以减少协程的创建和销毁,提高协程的复用率,降低系统开销。在 Go 中,可以使用 sync.Pool 或第三方库实现协程池。

示例代码:

package main

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

type Task struct {
    id int
}

func NewTask(id int) *Task {
    return &Task{id: id}
}

func (t *Task) Run() {
    fmt.Printf("task %d is running\n", t.id)
    time.Sleep(time.Second)
}

func main() {
    // 创建协程池,大小为 5
    pool := sync.Pool{
        New: func() interface{} {
            return make(chan *Task)
        },
    }

    // 创建任务队列,大小为 10
    tasks := make([]*Task, 10)
    for i := 0; i < 10; i++ {
        tasks[i] = NewTask(i)
    }

    // 将任务放入任务队列
    taskChan := make(chan *Task)
    go func() {
        for _, task := range tasks {
            taskChan <- task
        }
        close(taskChan)
    }()

    // 执行任务
    var wg sync.WaitGroup
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()

            for task := range taskChan {
                ch := pool.Get().(chan *Task)
                ch <- task
                go func() {
                    task.Run()
                    pool.Put(ch)
                }()
            }
        }()
    }

    wg.Wait()
}

在这个示例中,我们创建了一个大小为 5 的协程池,将大小为 10 的任务队列放入一个 taskChan 中,并通过协程池来执行任务。在协程池中,我们使用 sync.Pool 来管理协程的池子,通过 pool.Get() 来获取一个协程,将任务放入协程中执行,然后再将协程放回协程池中。