Golang

关注公众号 jb51net

关闭
首页 > 脚本专栏 > Golang > Go协程池

Golang协程池的实现与应用

作者:未来谁可知

这篇文章主要介绍了Golang协程池的实现与应用,使用协程池的好处是减少在创建和销毁协程上所花的时间以及资源的开销,解决资源不足的问题,需要详细了解可以参考下文

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协程池内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文