Go学习笔记—工作池

Go学习笔记—工作池、等待组、速率限制


1、工作池 Worker Pools

工作池可以让goroutine安全的共享资源。

通过goroutinechannel实现。

func worker(id int,jobs <-chan int,results chan<- int){
    for j := range jobs{
        fmt.Println("worker",id,"processing job",j)
        time.Sleep(time.Second * 2)
        results <- j * 2 // 接收通道接收任务后,向results通道发送结果
    }
}

func main(){
    jobs := make(chan int,100)
    results := make(chan int,100)

    for w := 1;w <= 3;w++{
        go worker(w,jobs,results) // 创建3个工作池
    }

    for j:=1;j<=9;j++{
        jobs <- j // 向工作池接收通道发送任务
    }
    close(jobs) // 关闭jobs通道

    for i:=1;i<=9;i++{
        <-results // results通道接收到结果,工作池结束
    }
}

定义工作池worker,参数jobs为接收通道,results为发送通道,id是工作池编号。

工作池的运行时并行的。

2、等待组 WaitGroups

可以使用WaitGroups等待多个协程goroutine完成。

使用sync.WaitGroup定义一个接受者,即可使用等待组的功能。

var wg sync.WaitGroup

wg.Done()

WaitGroup做函数参数时,要使用指针。

func working(id int,wg *sync.WaitGroup){
    defer wg.Done()

    fmt.Println("Worker",id,"starting") // 先输出
    time.Sleep(time.Second * 6)
    fmt.Println("Worker",id,"done") // 6秒后输出
}

func main(){
    var wg sync.WaitGroup

    for i:=1;i<=5;i++{
        wg.Add(1)
        go working(i,&wg)
        time.Sleep(time.Second) // 输出间隔1秒
    }

    wg.Wait()
}

//Worker 1 starting
//Worker 2 starting
//Worker 3 starting
//Worker 4 starting
//Worker 5 starting
//Worker 1 done
//Worker 2 done
//Worker 3 done
//Worker 4 done
//Worker 5 done
//主函数在运行之后,每间隔1秒输出一次`Worker 1 starting`,输出5次后,等待1秒,再输出`Worker 1 done`。

利用sleep来模拟阻塞状态。

根据实例可以看出,当添加了WaitGroup后,主函数会在所有的goroutine运行结束后,再结束。

  • .Done():返回所有goroutine结束运行的状态
  • .Add():将参数添加到WaitGroup计数器
  • .Wait():等待goroutine运行结束,结束主程序

3、速率限制 Rate Limiting

速率限制是一个重要的控制服务资源利用和质量的途径。

通过goroutinechannelticker实现。

func main(){
    requests := make(chan int,5)
    for i := 1;i <= 5;i++{
        requests <- i
    }
    close(requests)

    limiter := time.Tick(time.Second)

    for req := range requests{
        <- limiter
        fmt.Println("request",req,time.Now())
    }
    // 上部分模拟限制速率的传输

    burstyLimiter := make(chan time.Time,3)

    for i := 0;i<3;i++{
        burstyLimiter <- time.Now()
    }

    go func() {
        for t := range time.Tick(time.Second){
            burstyLimiter <- t
        }
    }()
    // 模拟整体的速率控制

    burstyRequests := make(chan int,5)
    for i:=1;i<=5;i++{
        burstyRequests <- i
    }
    close(burstyRequests)
    for req := range burstyRequests{
        <- burstyLimiter
        fmt.Println("request",req,time.Now())
    }
    // 模拟超过5个介入请求,在通道缓冲影响下的结果
}

你可能感兴趣的:(认真学Go,go,golang)