什么??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中的时间完全完成之后才可以结束文件。

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

相关推荐
lazy H30 分钟前
从入门到日常开发,一篇文章掌握 Git 核心操作
git·后端·学习·github
GetcharZp9 小时前
抛弃低效SSH!这套Ansible+Web可视化神器,让你天天准点下班!
后端
weixin_4462608512 小时前
HACO:面向动态部署环境的对冲式智能计算可靠多智能体调度框架
后端·python·flask
ttwuai13 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang
用户83562907805113 小时前
Python 实现 Excel 页面布局与打印设置自动化
后端·python
用户99314415798413 小时前
微服务框架中获取用户信息
后端
xuanWb13 小时前
手写一个 LLM API 网关:Anthropic 与 OpenAI 协议转换的完整实现
后端
苍何14 小时前
给 Codex 换皮肤这门生意,被我开源了
后端
用户83562907805114 小时前
Python 实现 Excel 命名范围(Named Range)的创建与管理
后端·python