• golang - 实现并发数控制的方法


    golang并发

    谈到golang这门语言,很自然的想起了他的的并发goroutine。这也是这门语言引以为豪的功能点。并发处理,在某种程度上,可以提高我们对机器的使用率,提升系统业务处理能力。但是并不是并发量越大越好,太大了,硬件环境就会吃不消,反而会影响到系统整体性能,甚至奔溃。所以,在使用golang提供便捷的goroutine时,既要能够实现开启并发,也要学会如果控制并发量。

    开启golang并发

    golang开启并发处理非常简单,只需要在调用函数时,在函数前边添加上go关键字即可。如下边例子所示:

    ?

    package main

    import (

      "fmt"

      "time"

    )

    type Demo struct {

      input     chan string

      output    chan string

      max_goroutine chan int

    }

    func NewDemo() *Demo {

      d := new(Demo)

      d.input = make(chan string, 24)

      d.output = make(chan string, 24)

      d.max_goroutine = make(chan int, 20)

      return d

    }

    func (this *Demo) Goroutine() {

      var i = 1000

      for {

        this.input <- time.Now().Format("2006-01-02 15:04:05")

        time.Sleep(time.Second * 1)

        if i < 0 {

          break

        }

        i--

      }

      close(this.input)

    }

    func (this *Demo) Handle() {

      for t := range this.input {

        fmt.Println("datatime is :", t)

        this.output <- t

      }

    }

    func main() {

      demo := NewDemo()

      go demo.Goroutine()

      demo.Handle()

    }

    上边代码,在调用Demo的Goroutine方法时,在前边加上了go关键字,则函数Goroutine并发执行开启成功。

    可见,在golang中开启并发非常的方便。

    下边再来看看,在golang中,怎么实现并发量的控制。

    当goroutine并发执行的任务达到一定值时,主程序等待goroutine执行完成退出,一旦发现并发数量低于某一个设定的值,就从新开始执行主程序逻辑。

    实现代码如下:

    ?

    package main

    import (

      "fmt"

      "time"

    )

    type Demo struct {

      input     chan string

      output    chan string

      goroutine_cnt chan int

    }

    func NewDemo() *Demo {

      d := new(Demo)

      d.input = make(chan string, 8192)

      d.output = make(chan string, 8192)

      d.goroutine_cnt = make(chan int, 10)

      return d

    }

    func (this *Demo) Goroutine() {

      this.input <- time.Now().Format("2006-01-02 15:04:05")

      time.Sleep(time.Millisecond * 500)

      <-this.goroutine_cnt

    }

    func (this *Demo) Handle() {

      for t := range this.input {

        fmt.Println("datatime is :", t, "goroutine count is :", len(this.goroutine_cnt))

        this.output <- t + "handle"

      }

    }

    func main() {

      demo := NewDemo()

      go demo.Handle()

      for i := 0; i < 10000; i++ {

        demo.goroutine_cnt <- 1

        go demo.Goroutine()

      }

      close(demo.input)

    }

    如上边示例,Goroutine()函数,每隔500毫秒写入一个时间戳到管道中,不考虑管道的读取时间,也就是说,每个Goroutine会存在大概500毫秒时间,如果不做控制的话,一瞬间可以开启上万个甚至更多的goroutine出来,这样系统就会奔溃。

    在上述代码中,我们引入了带10个buffer的chan int字段,每创建一个goroutine时,就会向这个chan中写入一个1,每完成一个goroutine时,就会从chan中弹出一个1。当chan中装满10个1时,就会自动阻塞,等待goroutine执行完,弹出chan中的值时,才能继续开启goroutine。通过chan阻塞特点,实现了goroutine的最大并发量控制。

  • 相关阅读:
    微信小程序修改van-popup的背景颜色
    计算机组成原理——指令系统の选择题整理
    有效供应链管理的八大绩效分析指标(上)
    HBase-shell命令
    精简版 — Hive开发常用操作
    10/16作业
    南美委内瑞拉市场最全分析开发攻略,收藏一篇就够了
    【建议收藏】50 道硬核的 Python 面试题!
    基于SSH开发美食网系统网站+论文+PPT+开题报告+任务书+外文翻译 毕业设计
    Go float精度 .00值判断
  • 原文地址:https://blog.csdn.net/xuezhangjun0121/article/details/132685904