本文共 1456 字,大约阅读时间需要 4 分钟。
为防止无限制开启gorouting造成的cpu性能浪费以及更严重的内存溢出和程序崩溃,这里加单实现一下协程池
深入理解:
流程图:
代码实现:
package mainimport ( "fmt" "time")//----------------------有关任务的功能-----------//定义一个任务类型type Task struct { f func() error //一个Task里有一个具体的业务,业务名称叫f}//创建一个Task任务func NewTask(arg_f func() error) *Task { return &Task{f:arg_f}}//task执行业务的方法func (t *Task) Execute() { err := t.f() //真正执行具体业务 if err != nil { fmt.Println("任务出错:", err) }}//----------------------有关协程池Pool的功能-----------//定义协程池type Pool struct { //对外的task入口 EntryChannel chan *Task //内部的task队列 JobsChannel chan *Task //协程池中worker数量 worker_num int}//创建协程池func NewPool(cap int) *Pool{ return &Pool{ EntryChannel:make(chan *Task), JobsChannel:make(chan *Task), worker_num:cap, }}//协程池创建一个worker,让这个worker取队列里拿任务执行func (p *Pool) startOneWorker(worker_ID int){ //一直永久地从JobsChannel取任务 for task := range p.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.startOneWorker(i) } //从EntryChannel中取任务,将新任务发给内部队列JobsChannel for task := range p.EntryChannel{ p.JobsChannel <- task }}func main() { //1.创建一些任务。这里示例用循环重复一个任务 t := NewTask(func() error { fmt.Println(time.Now()) return nil }) //2.创建容量为4的协程池 p := NewPool(4) task_num := 0 //3.将任务放入协程池外部接口 go func() { for { p.EntryChannel <- t task_num ++ fmt.Println("当前一个执行了 ",task_num," 个任务!") } }() //4.启动pool p.run()}
转载地址:http://gzwsi.baihongyu.com/