亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

程序因頻道而掛起

程序因頻道而掛起

Go
慕桂英4014372 2023-07-31 17:32:54
我想使用 goroutine 來批量處理來自不同客戶的不同日期的請求。我的意思是 50 個消費者 goroutine 來消費數據庫中的所有客戶,以及 2 個日期消費者 goroutine 來消費日期切片。主要代碼如下,但它掛起并且沒有按預期退出。為什么它沒有按預期退出?func Run(){    var syncWg sync.WaitGroup    syncWg.Add(1)    go SyncCustomerMetricsHistory(&syncWg)    syncWg.Wait()}func SyncCustomerMetricsHistory(wg *sync.WaitGroup){    defer wg.Done()    odb := orm.NewOrm()    start := time.Now()    logs.Info("start sync  customer metrics, time:[%v]", start)    qs := odb.QueryTable("gg_customer")    var customers []*db.GgCustomer    if num, err := qs.All(&customers); err != nil || num == 0 {        logs.Error("Get customer error, rows:[%v], err:[%v]", num, err)    }    customersChan := make(chan *db.GgCustomer, 50)    var wgC sync.WaitGroup    wgC.Add(50)    for i := 0; i < 50; i++ {        go syncCustomerMetricsHistory(customersChan, &wgC)    }    go func() {        for _, customer := range customers {            customersChan <- customer        }        close(customersChan)    }()    wgC.Wait()}func  syncCustomerMetricsHistory(customerChan <- chan *db.GgCustomer, wg *sync.WaitGroup){    defer wg.Done()    for customer := range customerChan{            dateChan := make(chan string, 2)            var wgD sync.WaitGroup            wgD.Add(2)            for i := 1; i < 2; i++{                go test(dateChan, customer, &wgD)            }            go func(){                for _, date := range GetAllYearDate(){                    dateChan <- date                }                close(dateChan)            }()            wgD.Wait()        }    }}func test(dateChan <- chan string, customer *db.GgCustomer, wg *sync.WaitGroup){    defer wg.Done()    for date := range dateChan{        fmt.Println(date, customer)    }}func  GetAllYearDate()  []string{  return []string{"2019-10-01", "2019-10-02"}}
查看完整描述

1 回答

?
四季花海

TA貢獻1811條經驗 獲得超5個贊

我沒有嘗試運行這個(因為它需要額外的代碼),但相信你的問題是:


wgD.Add(2)

for i := 1; i < 2; i++{

 go test(dateChan, customer, &wgD)

}

該 for 循環只會迭代一次,但您調用了 wgD.Add(2) (我認為您可能意味著循環迭代兩次;嘗試i <= 2)。


另一點反饋;您使用等待組的方式會起作用,但很難遵循(可能導致您沒有發現問題);怎么樣:


func Run(){

    SyncCustomerMetricsHistory()  // No wait group needed as this will not return before done

}


func SyncCustomerMetricsHistory(){

    odb := orm.NewOrm()

    start := time.Now()

    logs.Info("start sync  customer metrics, time:[%v]", start)


    qs := odb.QueryTable("gg_customer")

    var customers []*db.GgCustomer

    if num, err := qs.All(&customers); err != nil || num == 0 {

        logs.Error("Get customer error, rows:[%v], err:[%v]", num, err)

    }


    customersChan := make(chan *db.GgCustomer, 50)


    var wgC sync.WaitGroup

    wgC.Add(50)

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

        go func() {

            syncCustomerMetricsHistory(customersChan)

            wgC.Done()

        }()

    }


    go func() {

        for _, customer := range customers {

            customersChan <- customer

        }

        close(customersChan)

    }()

    wgC.Wait()

}




func  syncCustomerMetricsHistory(customerChan <- chan *db.GgCustomer){

    for customer := range customerChan{

            dateChan := make(chan string, 2)

            var wgD sync.WaitGroup

            wgD.Add(2)

            for i := 1; i < 2; i++{

                go func() {

                    test(dateChan, customer)

                    wgD.Done()

                }()

            }

            go func(){

                for _, date := range GetAllYearDate(){

                    dateChan <- date

                }

                close(dateChan)

            }()

            wgD.Wait()

        }

    }

}

我認為這更容易理解,因為您可以看到 wg.Done() 被調用的位置。在兩側粘貼一些 fmt.Println 命令也非常容易,這使得調試此類問題變得更簡單。


查看完整回答
反對 回復 2023-07-31
  • 1 回答
  • 0 關注
  • 192 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號