goroutine池是一种管理goroutine的方式,它可以控制同时运行的goroutine的数量,避免因为创建过多的goroutine而导致的资源耗尽
- 首先创建了一个WorkerPool结构体,它包含一个jobs通道和一个sync.WaitGroup。 jobs通道用于接收任务,
sync.WaitGroup用于等待所有的goroutine完成。 - NewWorkerPool函数创建一个新的WorkerPool,并启动指定数量的goroutine。每个goroutine都会从jobs通道中读取任务并执行。
- AddJob函数将一个新的任务添加到jobs通道。 Wait函数关闭jobs通道,并等待所有的goroutine完成。
- 在main函数中,创建了一个新的WorkerPool,并添加了10个任务。每个任务都是一个简单的函数,它打印一条消息。然后调用Wait函数等待所有的任务完成
package main
import (
"fmt"
"sync"
)
type Job func()
type WorkerPool struct {
jobs chan Job
wg sync.WaitGroup
}
func NewWorkerPool(maxGoroutines int) *WorkerPool {
pool := &WorkerPool{
jobs: make(chan Job),
}
pool.wg.Add(maxGoroutines)
for i := 0; i < maxGoroutines; i++ {
go func() {
for job := range pool.jobs {
job()
}
pool.wg.Done()
}()
}
return pool
}
func (p *WorkerPool) AddJob(job Job) {
p.jobs <- job
}
func (p *WorkerPool) Wait() {
close(p.jobs)
p.wg.Wait()
}
func main() {
pool := NewWorkerPool(5)
for i := 0; i < 10; i++ {
i := i
pool.AddJob(func() {
fmt.Printf("Job %d is running\n", i)
})
}
pool.Wait()
}
每个goroutine都会不断地从pool.jobs这个channel中获取job,完成一个job后会继续获取下一个job,直到pool.jobs被关闭。因此,每个goroutine完成的job是不确定的,它取决于它何时从pool.jobs获取到job。
如果想在打印日志时知道一个job是由哪个goroutine完成的,可以在每个goroutine启动时为其分配一个唯一的ID,然后在执行job时将这个ID传递给job。这样,当job在执行时,它就可以知道自己是由哪个goroutine执行的。
下面代码为每个goroutine分配了一个唯一的ID,并在执行job时打印这个ID
首先修改了Job类型,使其接收一个goroutine ID作为参数。然后在NewWorkerPool函数中,为每个goroutine分配了一个唯一的ID,并在启动goroutine时将这个ID传递给它。
package main
import (
"fmt"
"sync"
)
type Job func(id int)
type WorkerPool struct {
jobs chan Job
wg sync.WaitGroup
}
func NewWorkerPool(maxGoroutines int) *WorkerPool {
pool := &WorkerPool{
jobs: make(chan Job),
}
pool.wg.Add(maxGoroutines)
for i := 0; i < maxGoroutines; i++ {
go func(id int) {
for job := range pool.jobs {
job(id)
}
pool.wg.Done()
}(i)
}
return pool
}
func (p *WorkerPool) AddJob(job Job) {
p.jobs <- job
}
func (p *WorkerPool) Wait() {
close(p.jobs)
p.wg.Wait()
}
func main() {
pool := NewWorkerPool(5)
for i := 0; i < 10; i++ {
i := i
pool.AddJob(func(id int) {
fmt.Printf("Job %d is running by goroutine %d\n", i, id)
})
}
pool.Wait()
}