package main
import (
"fmt"
"time"
)
//---------------------------以下有关Task任务角色的功能
//定义一个任务类型 Task
type Task struct {
function func() error //一个Task里面应该有一个具体的业务,业务名称叫function
}
//创建一个任务
func NewTask(arg_f func() error) *Task {
t := Task{
function: arg_f,
}
return &t
}
//Task也需要一个执行业务的方法
func (t *Task) Execute() {
t.function() //调用任务已经绑定好的业务方法
}
//---------------------------以下有关协程池角色的功能
//定义一个Pool协程池类型
type Pool struct {
//对外的Task入口 EntryChannel
Entrychannel chan *Task
//内部的Task队列 JobsChannel
JobsChannel chan *Task
//协程池中最大的协程数
worker_num int
}
//创建一个Pool
func NewPool(cap int) *Pool {
//创建一个Pool
p := Pool{
Entrychannel: make(chan *Task),
JobsChannel: make(chan *Task),
worker_num: cap,
}
return &p
}
//协程池创建一个worker,并让worker去工作
func (p *Pool) worker(worker_id int) {
//一个worker的具体工作
//永久的从JobsChannel去取任务
for task := range p.JobsChannel {
//task 就是当前worker从jobschannel中取到的任务
//取到任务就执行
task.Execute()
fmt.Println("worker id ", worker_id, " 执行了一个任务")
}
}
//让协程池开始真正的工作
func (p *Pool) run() {
//根据worker_num 来创建worker去工作
for i := 0; i < p.worker_num; i++ {
go p.worker(i)
}
//不断从entrychannel中取任务,将取到的任务放到jobschannel中
for task := range p.Entrychannel {
//一旦入口有任务,放入jobschannel
p.JobsChannel <- task
}
}
//主函数 来测试协程池的工作
func main() {
//创建一些任务
t := NewTask(func() error {
//当前任务的业务逻辑-匿名函数
fmt.Println(time.Now())
return nil
})
//创建协程池-协程数4
p := NewPool(4000)
task_num := 0
//将这些任务交给协程池
go func() {
for {
//不断的向P中写入任务
p.Entrychannel <- t
task_num += 1
fmt.Println("当前一共执行了 ", task_num, " 个任务")
}
}()
//启动Pool
p.run()
}
golang 协程池
最新推荐文章于 2025-02-24 20:45:11 发布