如何通过通道实现Goroutine池

  介绍

这篇文章主要为大家展示了“如何通过通道实现Goroutine池”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“如何通过通道实现Goroutine池”这篇文章吧。

最近用到了去从Excel导数据到服务器内部用的是http请求
但是发现一个问题从文件读取之后新开Goroutine会无限制新增
导致全部卡在初始化请求于是乎就卡死了

问题模拟

<李>

模拟代码

 func 主要(),{
  ,,,pool :=, sync.WaitGroup {}
  ,,,for 小姐::=,0;,小姐:,lt;, 500;,我+ +,{
  ,,,,,,,pool.Add (1)
  ,,,,,,,go  func(小姐:int), {
  ,,,,,,,,,,,,err 职责:=,http.Get (“http://ip.3322.org")
  ,,,,,,,,,,,if  err  !=, nil  {
  ,,,,,,,,,,,,,,,fmt.Println(我,犯错)
  ,,,,,,,,,,,},{else 
  ,,,,,,,,,,,,,,,defer  resp.Body.Close ()
  ,,,,,,,,,,,,,,,,,_ :=, ioutil.ReadAll (resp.Body)
  ,,,,,,,,,,,,,,,fmt.Println(我,字符串(结果))
  ,,,,,,,,,,,}
  ,,,,,,,,,,,pool.Done ()
  ,,,,,,,}(我)
  ,,,}
  ,,,pool.Wait ()
  }
<李>

数量小的情况下没有问题但是数量比较大的情况就会发现程序直接卡死一段时间之后报错并且没有发出任何请求

问题解决

<李>

实际上看的出来是应为同时发起了太多的HTTP请求导致系统卡死数据没有发送

<李>

想到我在Java中用线程提交请求我就考虑可不可限制Goroutine的数量

<李>

使用强大的百度果然找到了大佬已经写好的协程池

<李>

代码如下我加上了注释

 package  gopool
  
  import  (
  ,,,“sync"
  )//,Pool  Goroutine 池
  type  Pool  struct  {
  ,,,queue  chan  int
  ,,,wg ,, * sync.WaitGroup
  }//,New 新建一个协程池
  func 新(size  int), * Pool  {
  ,,,if  size , lt;=, 0, {
  ,,,,,,,size =1
  ,,,}
  ,,,return , amp;池{
  ,,,,,,,队列:,让(int, chan 大小),
  ,,,,,,,wg:,,,,,, sync.WaitGroup {},
  ,,,}
  }//,Add 新增一个执行
  func  (p  *池),添加(delta  int), {
  ,,,//,δ为正数就添加
  ,,,for 小姐::=,0;,小姐:,lt;,三角洲;,我+ +,{
  ,,,,,,,p.queue , lt;作用;1
  ,,,}
  ,,,//,δ为负数就减少
  ,,,for 小姐::=,0;,小姐:和gt;,三角洲;,我——,{
  ,,,,,,,,lt; -p.queue
  ,,,}
  ,,,p.wg.Add(δ)
  }//,Done 执行完成减一
  func  (p  *池),完成(),{
  ,,,,lt; -p.queue
  ,,,p.wg.Done ()
  }//,Wait 等待Goroutine执行完毕
  func  (p  *池),等待(),{
  ,,,p.wg.Wait ()
  }
<李>

然后修改刚才的测试方法

 package 主要
  
  import  (
  ,,,“io/ioutil"
  ,,,“log"
  ,,,“;net/http"
  ,,,“yumc.pw/云/lib/gopool"
  )
  
  func  main (), {
  ,,,//,这里限制5个并发
  ,,,pool :=, gopool.New (5)//, sync.WaitGroup {}
  ,,,for 小姐::=,0;,小姐:,lt;, 500;,我+ +,{
  ,,,,,,,pool.Add (1)
  ,,,,,,,go  func(小姐:int), {
  ,,,,,,,,,,,,err 职责:=,http.Get (“http://ip.3322.org")
  ,,,,,,,,,,,if  err  !=, nil  {
  ,,,,,,,,,,,,,,,fmt.Println(我,犯错)
  ,,,,,,,,,,,},{else 
  ,,,,,,,,,,,,,,,defer  resp.Body.Close ()
  null
  null
  null
  null
  null
  null
  null
  null

如何通过通道实现Goroutine池