这里写自定义目录标题
只用channel就可以实现高效简洁的协程池
只使用channel,而不用go的waitgroup等其他元素,就可以实现协程复用,并且高效简洁,废话不多说直接show your code!
package main
import (
"fmt"
"time"
)
type WorkerPool struct {
maxCapacity int
workerChannel chan chan func()
closeChannel chan func()
}
func NewWorkerPool(capacity int) *WorkerPool {
return &WorkerPool{
maxCapacity: capacity,
workerChannel: make(chan chan func(), capacity),
closeChannel: make(chan func()),
}
}
func (wp *WorkerPool) Start() {
for i := 0; i < wp.maxCapacity; i++ {
go wp.startWorker()
}
}
func (wp *WorkerPool) startWorker() {
worker := make(chan func())
wp.workerChannel <- worker
for {
select {
case task := <-worker:
task() // 执行任务
wp.workerChannel <- worker // 将协程重新放回可用协程通道
case <-wp.closeChannel: // 接收任务通道的关闭信号
return
}
}
}
func (wp *WorkerPool) Execute(task func()) {
worker := <-wp.workerChannel // 从可用协程通道获取一个协程
worker <- task // 将任务发送给协程执行
}
func main() {
pool := NewWorkerPool(5) // 创建一个最大容量为5的协程池
pool.Start()
now := time.Now()
for i := 0; i < 10000; i++ {
taskID := i
pool.Execute(func() {
fmt.Printf("Task %d completed\n", taskID)
})
}
close(pool.closeChannel) // 关闭任务通道,通知协程池停止接收新任务
//fmt.Println("Num:", runtime.NumGoroutine())
fmt.Println("cost_time:", time.Since(now))
}