Golang协程池的实现与应用
短信预约 -IT技能 免费直播动态提醒
1. 为什么需要协程池
使用协程池的好处是减少在创建和销毁协程上所花的时间以及资源的开销,解决资源不足的问题。如果不使用协程池,有可能造成系统创建大量同类协程池而导致消耗完内存或者内存泄漏的问题。
2. 使用协程池的优点
- 不用手动频繁的创建协程了
- 方便统一管理,只用管理池子就行了
- 提高响应速度,一有任务如果有刚执行完的协程就能马上去执行新任务
3. 设计思路
Task 任务对象->EntryChannel->JobsChannel <-Pool(worker)
4. 实现一个简单的协程池
4.1 Task 任务对象
type Task struct {
// Task方法 任务
method func() error
// 可以扩展
}
// NewTask 创建一个Task
func NewTask(method func() error) *Task {
return &Task{
method: method,
}
}
// Execute 任务执行
func (t *Task) Execute() {
err := t.method()
if err != nil {
panic(err)
}
}
4.2 Pool协程池
// 定义一个协程池
type Pool struct {
// 对外的Task入口
EntryChannel chan *Task
// 对内的Task队列
JobsChannel chan *Task
// 协程池的最大work数量
WorkerNum int
}
// NewPool 创建Pool的函数
func NewPool(cap int) *Pool{
return &Pool{
EntryChannel: make(chan *Task),
JobsChannel: make(chan *Task),
WorkerNum: cap,
}
}
// 协程池创建一个Worker
func (p *Pool)worker(workID int){
for task:=range p.JobsChannel{
task.Execute() //取到任务就执行
fmt.Println("worker_id 为",workID)
}
}
// 让协程池开始真正的工作
func (p *Pool)run() {
// 根据创建协程池的大小来创建协程工作
for i := 0; i < p.WorkerNum; i++ {
go p.worker(i+1)
}
// 不断遍历外部的任务然后丢入到内部的队列去运行
for task := range p.EntryChannel {
p.JobsChannel<-task
}
}
4.3 Main函数
// 主函数 测试
func main(){
// 创建一些任务
task:=NewTask(PrintTimeNow)
// 创建协程池
pool:=NewPool(4)
taskNum:=0
go func(taskNum int) {
for{
// 不断的向池子里写入任务task,任务主要是打印当前时间
pool.EntryChannel<-task
// atomic.AddInt32(&taskNum,1)
taskNum+=1
fmt.Println("当前一共执行了",taskNum,"个任务")
}
}(taskNum)
pool.run()
}
// 业务逻辑
func PrintTimeNow()( err error){
fmt.Println(time.Now())
return
}
到此这篇关于Golang协程池的实现与应用的文章就介绍到这了,更多相关Go协程池内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341