什么??go中的协程池竟然.........

什么是协程池

协程池简单理解就是有一个池子一样的东西,里面装这个固定数量的goroutine,当有一个任务到来的时候,会将这个任务交给池子里的一个空闲的goroutine去处理,如果池子里没有空闲的goroutine了,任务就会阻塞等待。

如何构建协程池

首先定义一个协程池的结构体

go 复制代码
type WorkerPool struct {
    Jobs    chan func()//公共的通道,到时候任务写进这里面
    MaxWorkers int//设置协程池最多有多少个协程
}

然后创建一个协程

go 复制代码
func NewWorkerPool(maxWorkers int) *WorkerPool {
    pool := &WorkerPool{
        Jobs:       make(chan func()),//初始化
        MaxWorkers: maxWorkers,
    }
    for i := 0; i < pool.MaxWorkers; i++ {
        go pool.worker()//这里就是创建多个协程
    }
    return pool
}
go 复制代码
func (p *WorkerPool) worker() {
    for job := range p.Jobs {//这里就是从公共通道里面获取任务
        job()
    }
}

以上,最简单的协程池就算创建好了。

协程池的使用

go 复制代码
func (p *WorkerPool) AddJob(job func()) {
    p.Jobs <- job
}

这里就是将任务函数传进通道里,然后公平地分给各个空闲的协程。

协程池的关闭

go 复制代码
func (p *WorkerPool) Close() { 
     close(p.Jobs) 
}

完整健壮的协程池

go 复制代码
type WorkerPool struct {
    Jobs         chan func()
    MaxWorkers   int
    wg           sync.WaitGroup // 新增:任务完成计数器
}

func NewWorkerPool(maxWorkers int) *WorkerPool {
    pool := &WorkerPool{
        Jobs:       make(chan func()),//初始化
        MaxWorkers: maxWorkers,
    }
    for i := 0; i < pool.MaxWorkers; i++ {
        go pool.worker()//这里就是创建多个协程
    }
    return pool
}

func (p *WorkerPool) worker() {
    
    for job := range p.Jobs {//这里就是从公共通道里面获取任务
        defer func() {
                if r := recover(); r != nil {
                    log.Printf("Worker panic: %v", r)
                 }
         }()
         
         job()
         
     }
}

func (p *WorkerPool) AddJob(job func()) {
	p.wg.Add(1) // 任务数+1
	p.Jobs <- func() {        //这里的func匿名函数就是上面的job处理函数
            defer p.wg.Done()
            job()              // 执行实际任务
	}
}

func (p *WorkerPool) Wait() {
	p.wg.Wait() // 阻塞直到所有任务完成
}

func main() {
	pool := NewWorkerPool(2)

	// 添加 3 个任务
	pool.AddJob(func() { time.Sleep(1 * time.Second) })
	pool.AddJob(func() { time.Sleep(1 * time.Second) })
	pool.AddJob(func() { time.Sleep(1 * time.Second) })

	// 主协程等待任务完成
	defer fmt.Println("主协程结束")
	pool.Wait() // **关键:阻塞在这里直到所有任务完成**
}

上面的代码添加了

go 复制代码
sync.WaitGroup

defer func() {
    if r := recover(); r != nil {
        log.Printf("Worker panic: %v", r) 
        } 
 }()

第一个用来确保在channel中的时间完全完成之后才可以结束文件。

第二个用来确保在每个任务出现问题时不会影响整个协程池的正常运行

相关推荐
货拉拉技术30 分钟前
构建稳定的 AI Agent:Harness 工程的核心机制与实践思考
人工智能·后端·数据分析
hsfxuebao42 分钟前
Harness工程
后端·架构
暗夜行者之光1 小时前
LangGraph 实战:构建“自我修正”的代码生成 Agent
后端
IT枫斗者枫哥1 小时前
AI返回合法JSON,字段就可信吗?给抽取结果补一道业务校验
java·人工智能·后端
IT枫斗者枫哥1 小时前
同一个requestId换了参数,为什么不能直接返回旧结果?
java·后端
溪语流沙1 小时前
Django + Vue电商项目第005讲:后端骨架|Django初始化、配置分层与DRF接入
vue.js·后端·python·django
益达是我啊1 小时前
前端工程师的 Java 后端 30 天快速入门(1)
后端
136096757231 小时前
apt-get 补的库,一次重建全没了
后端
IT枫斗者枫哥1 小时前
ORDER BY时间还会漏单?用相同时间和插入记录测一次分页
java·后端
IT枫斗者枫哥1 小时前
UPDATE影响0行,接口却返回成功:把版本冲突接回业务
java·后端