在Go中应用goroutine池,一般是为了限制同时运行的goroutine数量,以避免资源过度消耗。goroutine池可以通过创建一个工作队列和一个固定数量的工作者来实现。以下是一个goroutine池的实现示例:
package main
import (
"fmt"
"time"
)
// Job 表示需要处理的任务
type Job struct {
id int
workload int
}
// Worker 表示工作者
func Worker(id int, jobs <-chan Job, results chan<- int) {
for job := range jobs {
fmt.Printf("Worker %d processing job %d\n", id, job.id)
time.Sleep(time.Duration(job.workload) * time.Second) // 模拟工作时间
results <- job.id
}
}
func main() {
const numJobs = 5 // 总任务数
const numWorkers = 3 // 工作者数
jobs := make(chan Job, numJobs) // 创建任务队列
results := make(chan int, numJobs) // 创建结果队列
// 启动工作者
for w := range numWorkers {
go Worker(w, jobs, results)
}
// 发送任务到任务队列
for j := 0; j < numJobs; j++ {
jobs <- Job{id: j, workload: j + 1}
}
close(jobs) // 关闭任务队列
// 收集结果
for a := 0; a < numJobs; a++ {
result := <-results
fmt.Printf("Job %d done\n", result)
}
}
代码解析:
- Job结构体:表示一个任务,其中包含任务ID和工作负载(模拟任务所需的时间)。
- Worker函数:表示工作者,从
jobs
通道中获取任务并处理,然后将结果发送到results
通道。 - jobs通道:用于分发任务给工作者。
- results通道:用于接收工作者完成任务后的结果。
执行过程:
- 主函数中先创建了
jobs
和results
两个通道。 - 然后启动了一定数量的goroutine,每个goroutine都调用
Worker
函数并开始等待任务。 - 主程序将任务发送到
jobs
通道,然后关闭通道以表示没有更多任务。 - 最后,主程序等待从
results
通道接收所有任务的结果并输出。
通过这种方式,可以有效地控制同时运行的goroutine数量,避免系统资源过度消耗。