美文网首页
waitgroup+channel控制goroutine并发数量

waitgroup+channel控制goroutine并发数量

作者: 我爱张智容 | 来源:发表于2021-07-10 11:18 被阅读0次

版本一:

package main 
import (
      "fmt"
      "runtime"
      "sync"
)
var wg = sync.WaitGroup{}
// 任务业务流程
func business(ch chan bool, i int) {
  fmt.Println("go func", i, " goroutine count = ", runtime.NumGoroutine)
  <-ch
  wg.Done()
}

func main() {
  // 模拟用户需求的业务数量
  task_cnt := 10
  ch := make(chan bool, 3)
  for i := 0; i < taskk_cnt; i++ {
    wg.Add(1)
    // 如果channel满了,就会阻塞
    ch <- true  
    // 开启一个新协程
    go business(ch, i)
  }
  wg.Wait()
}

版本二:

package main 
import (
      "fmt"
      "runtime"
      "sync"
)
var wg = sync.WaitGroup{}
// 每个go的worker都要执行的一个工作流程
func business(ch chan int){
    // 消费一个任务
    for t := range ch {
        fmt.Println(" go task = ", t, ", goroutine count = ", runtime.NumGoroutine())
      wg.Done()
  }
}

// 发送一个任务(任务的输入,任务的生产)
func sendTask(task int, ch chan int) {
    wg.Add(1)
    ch <- task
}
func main() {
    // 无buffer的channel
    ch := make(chan int)
    // 1 启动goroutine工作池(go的数量是固定的)充当任务task的消费
    goCnt := 3
    for i := 0; i < goCnt; i++ {
      // 启动goroutine的worker
      go business(ch)
    }
    // 2模拟用户需求业务的数量,不断的给工作池发送task
    taskCnt := math.MaxInt64
    for t := 0; t < taskCnt; t++ {
        // 发送任务
        sendTask(t, ch)
    }
    wg.Wait()
}

版本三:

package gpool

import (
    "sync"
)

type pool struct {
    queue chan int
    wg    *sync.WaitGroup
}

func New(size int) *pool {
    if size <= 0 {
        size = 1
    }
    return &pool{
        queue: make(chan int, size),
        wg:    &sync.WaitGroup{},
    }
}

func (p *pool) Add(delta int) {
    for i := 0; i < delta; i++ {
        p.queue <- 1
    }
    for i := 0; i > delta; i-- {
        <-p.queue
    }
    p.wg.Add(delta)
}

func (p *pool) Done() {
    <-p.queue
    p.wg.Done()
}

func (p *pool) Wait() {
    p.wg.Wait()
}

测试代码:

package gpool_test

import (
    "runtime"
    "testing"
    "time"
    "gpool"
)

func Test_Example(t *testing.T) {
    pool := gpool.New(100)
    println(runtime.NumGoroutine())
    for i := 0; i < 1000; i++ {
        pool.Add(1)
        go func() {
            time.Sleep(time.Second)
            println(runtime.NumGoroutine())
            pool.Done()
        }()
    }
    pool.Wait()
    println(runtime.NumGoroutine())
}

相关文章

  • waitgroup+channel控制goroutine并发数量

    版本一: 版本二: 版本三: 测试代码:

  • Go语言小技巧(1)-控制并发数

    Go语言小技巧(1)-控制并发数 需求 虽然goroutine很廉价,但是有时候还是希望控制goroutine并发...

  • Go如何有效控制Goroutine并发数量

    相信大家在学习Go的过程中,都会看到类似这样一句话:"与传统的系统级线程和进程相比,协程的最大优势在于其‘轻量级’...

  • 来,控制一下 Goroutine 的并发数量

    原文地址:来,控制一下 Goroutine 的并发数量 问题 在这里,假设 userCount 是一个外部传入的参...

  • goroutine 数量控制

    goroutine 数量并不是越多越好,过多会占有太多的cpu资源和内存,可能使系统资源耗尽,所以goroutin...

  • Goroutine的并发控制

    模拟一下协程数量太多的危害: number过大,服务器系统资源利用率不断上涨,到最后程序自动killed 协程池解...

  • channel学习

    worker pool(goroutine池) 本质上是生产者消费者模型 可以有效控制goroutine数量,防止...

  • 并发

    控制并发有两种经典方式, WaitGroup:控制多个goroutine同时, var wg Sync.waitG...

  • Go context

    控制并发有两种经典的方式:WaitGroup和Context WaitGroup:控制多个Goroutine同时完...

  • GO 限制goroutine数量

    不控制goroutine数量引发的问题 Goroutine具备如下两个特点 体积轻量 优质的GMP调度 那么gor...

网友评论

      本文标题:waitgroup+channel控制goroutine并发数量

      本文链接:https://www.haomeiwen.com/subject/kgjzyltx.html