相信大家在学习Go的过程中,都会看到类似这样一句话:"与传统的系统级线程和进程相比,协程的最大优势在于其‘轻量级’,可以轻松创建上百万个而不会导致系统资源衰竭"。那是不是意味着我们在开发过程中,可以随心所欲的调用协程,而不关心它的数量呢?

答案当然是否定的。我们在开发过程中,如果不对Goroutine加以控制而进行滥用的话,可能会导致服务程序整体崩溃。

下面是通过channel和sync.WaitGroup实现控制

//协程池

package main

import (
    "fmt"
    "sync"
    "time"
)

//协程池

type Pool struct {
    num int //go协程数
    ch chan struct{}//任务队列
}

//初始化协程池

func NewPool(num int) *Pool {
    return &Pool{
        num: num,
        ch: make(chan struct{},num),
    }
}


var wg sync.WaitGroup
//任务处理函数

func Task(p *Pool)  {
    p.ch<- struct{}{}
    wg.Add(1)
    go func() {
        //fmt.Println(time.Now())
        time.Sleep(1*time.Second)
        <-p.ch //一定要加,不取出会死锁
        wg.Done()
    }()
}

func main()  {
    //1.创建协程对象
    p:=NewPool(50)
    //2.创建任务
    bT := time.Now()            // 开始时间
    for i := 0; i <100 ; i++ {
        Task(p)
    }
    wg.Done()
    close(p.ch)
    eT := time.Since(bT)      // 从开始到当前所消耗的时间
    fmt.Println("Run time: ", eT)
}

有不对的地方欢迎指出