协程池是一种常见的协程管理方式,它通过预先创建一定数量的协程,然后将任务放入一个任务队列中,由空闲的协程来执行任务。这样可以减少协程的创建和销毁,提高协程的复用率,降低系统开销。在 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() 来获取一个协程,将任务放入协程中执行,然后再将协程放回协程池中。