通過(guò) Channel 實(shí)現(xiàn) Goroutine Pool

最近用到了 Go 從 Excel 導(dǎo)數(shù)據(jù)到服務(wù)器內(nèi)部 用的是 http 請(qǐng)求
但是發(fā)現(xiàn)一個(gè)問(wèn)題 從文件讀取之后 新開(kāi) Goroutine 會(huì)無(wú)限制新增
導(dǎo)致全部卡在初始化請(qǐng)求 于是乎就卡死了

問(wèn)題模擬

  • 模擬代碼
func main() {
    pool := sync.WaitGroup{}
    for i := 0; i < 500; i++ {
        pool.Add(1)
        go func(i int) {
            resp, err := http.Get("http://ip.3322.org")
            if err != nil {
                fmt.Println(i, err)
            } else {
                defer resp.Body.Close()
                result, _ := ioutil.ReadAll(resp.Body)
                fmt.Println(i, string(result))
            }
            pool.Done()
        }(i)
    }
    pool.Wait()
}
  • 數(shù)量小的情況下 沒(méi)有問(wèn)題 但是數(shù)量比較大的情況 就會(huì)發(fā)現(xiàn)程序直接卡死 一段時(shí)間之后報(bào)錯(cuò) 并且沒(méi)有發(fā)出任何請(qǐng)求

問(wèn)題解決

  • 實(shí)際上看的出來(lái) 是應(yīng)為同時(shí)發(fā)起了太多的HTTP請(qǐng)求 導(dǎo)致系統(tǒng)卡死 數(shù)據(jù)沒(méi)有發(fā)送
  • 想到我在Java中用Thread提交請(qǐng)求 我就考慮 可不可限制 Goroutine 的數(shù)量
  • 使用強(qiáng)大的百度 果然找到了大佬已經(jīng)寫(xiě)好的協(xié)程池
  • 代碼如下 我加上了注釋
package gopool

import (
    "sync"
)

// Pool Goroutine Pool
type Pool struct {
    queue chan int
    wg    *sync.WaitGroup
}

// New 新建一個(gè)協(xié)程池
func New(size int) *Pool {
    if size <= 0 {
        size = 1
    }
    return &Pool{
        queue: make(chan int, size),
        wg:    &sync.WaitGroup{},
    }
}

// Add 新增一個(gè)執(zhí)行
func (p *Pool) Add(delta int) {
    // delta為正數(shù)就添加
    for i := 0; i < delta; i++ {
        p.queue <- 1
    }
    // delta為負(fù)數(shù)就減少
    for i := 0; i > delta; i-- {
        <-p.queue
    }
    p.wg.Add(delta)
}

// Done 執(zhí)行完成減一
func (p *Pool) Done() {
    <-p.queue
    p.wg.Done()
}

// Wait 等待Goroutine執(zhí)行完畢
func (p *Pool) Wait() {
    p.wg.Wait()
}
  • 然后修改剛才的測(cè)試方法
package main

import (
    "io/ioutil"
    "log"
    "net/http"
    "yumc.pw/cloud/lib/gopool"
)

func main() {
    // 這里限制5個(gè)并發(fā)
    pool := gopool.New(5)// sync.WaitGroup{}
    for i := 0; i < 500; i++ {
        pool.Add(1)
        go func(i int) {
            resp, err := http.Get("http://ip.3322.org")
            if err != nil {
                fmt.Println(i, err)
            } else {
                defer resp.Body.Close()
                result, _ := ioutil.ReadAll(resp.Body)
                fmt.Println(i, string(result))
            }
            pool.Done()
        }(i)
    }
    pool.Wait()
}
  • 完美解決
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Chapter 8 Goroutines and Channels Go enable two styles of...
    SongLiang閱讀 1,737評(píng)論 0 3
  • 第6天(8.15) 第三章,44~52頁(yè)。 一、理論知識(shí)摘要 1.和善而堅(jiān)定的養(yǎng)育,是一種注意長(zhǎng)期效果、鼓勵(lì)式的養(yǎng)...
    bdec4e2f6612閱讀 670評(píng)論 0 50
  • 姓名 顧春陽(yáng) 公司 揚(yáng)州市方圓建筑有限公司 打卡第251天 【知~學(xué)習(xí)】 《六項(xiàng)精進(jìn)》5遍 共927遍 《大學(xué)》5...
    顧春陽(yáng)閱讀 138評(píng)論 0 0
  • 第八章 偉才回家 如果想念一個(gè)人,就會(huì)變成微風(fēng),輕輕掠過(guò)他的身邊,就算他感覺(jué)不到可就是你全部的努力,人生就是這樣子...
    我不是蝸牛閱讀 265評(píng)論 0 2

友情鏈接更多精彩內(nèi)容