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

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

如何運行多個 goroutine 并按照運行順序收集結果

如何運行多個 goroutine 并按照運行順序收集結果

Go
楊__羊羊 2021-11-08 19:10:59
我有以下代碼,它具有雙重例程結構:package mainimport(    "fmt"    "math/rand"    "time"    "strconv")func main(){    outchan := make(chan string)    for i:=0;i<10;i++{        go testfun(i, outchan)    }    for i:=0;i<10;i++{        a := <-outchan        fmt.Println(a)    }}func testfun(i int, outchan chan<- string){    outchan2 := make(chan int)    time.Sleep(time.Millisecond*time.Duration(int64(rand.Intn(10))))    for j:=0;j<10;j++ {        go testfun2(j, outchan2)    }    tempStr := strconv.FormatInt(int64(i),10)+" - "    for j:=0;j<10;j++ {        tempStr = tempStr + strconv.FormatInt(int64(<-outchan2),10)    }    outchan <- tempStr}func testfun2(j int, outchan2 chan<- int){    time.Sleep(time.Millisecond*time.Duration(int64(rand.Intn(10))))    outchan2 <- j}我期待的輸出是0 - 01234567891 - 01234567892 - 01234567893 - 01234567894 - 01234567895 - 01234567896 - 01234567897 - 01234567898 - 01234567899 - 0123456789但是我得到了這個:7 - 79803452616 - 40358976213 - 90475268319 - 40328619758 - 95708316245 - 37980215461 - 09853624710 - 18492760352 - 95728061434 - 5768032419誰能告訴我如何實現我期望的輸出?我是新手,如果解決方案很明顯,請原諒我。我已經找了好幾天了。
查看完整描述

2 回答

?
當年話下

TA貢獻1890條經驗 獲得超9個贊

給你一個更好的主意。問題是您正在讀取單個通道,其中由于您的time.Sleep調用,推送到該通道上的值按任意順序排列。如果您想同時發出time.Sleep調用來模擬并發的長時間運行的進程,您需要做的是讓每個 goroutine 將結果寫入一個通道。


通過這種方式,您可以遍歷阻塞的結果通道的有序列表,直到可以從中讀取下一個通道(與此答案中的輸出隊列相同的想法在多線程管道中維護順序)名稱更改以使事情更容易跟蹤:


package main


import(

    "fmt"

    "math/rand"

    "time"

    "strconv"

)


func main(){

    var jobs []chan string

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

        job := make(chan string)

        jobs = append(jobs, job)

        go testfun(i, job)

    }

    for _, result := range jobs {

      fmt.Println(<-result)

    }

}


func testfun(i int, job chan<- string){

    var innerJobs []chan int

    time.Sleep(time.Millisecond*time.Duration(int64(rand.Intn(10))))

    for j := 0; j<10; j++ {

        innerJob := make(chan int)

        innerJobs = append(innerJobs, innerJob)

        go testfun2(j, innerJob)

    }

    tempStr := strconv.FormatInt(int64(i),10)+" - "

    for _, result := range innerJobs {

      tempStr = tempStr + strconv.FormatInt(int64(<-result),10)

    }

    job <- tempStr

}


func testfun2(j int, innerJob chan<- int){

    time.Sleep(time.Millisecond*time.Duration(int64(rand.Intn(10))))

    innerJob <- j

}


查看完整回答
反對 回復 2021-11-08
?
拉風的咖菲貓

TA貢獻1995條經驗 獲得超2個贊

一種不同/更有效的方法是使用切片(或數組)并使用sync.WaitGroup:


func main() {

    var wg sync.WaitGroup

    out := make([]string, 10)

    for i := 0; i < len(out); i++ {

        wg.Add(1)

        go testfun(i, &out[i], &wg)

    }

    wg.Wait()

    for i := 0; i < len(out); i++ {

        a := out[i]

        fmt.Println(a)

    }

}


func testfun(i int, outVal *string, wg *sync.WaitGroup) {

    //........

    *outVal = tempStr

    wg.Done()

}

playground


編輯:也更新了 testfun2 的示例,忘記了。


查看完整回答
反對 回復 2021-11-08
  • 2 回答
  • 0 關注
  • 278 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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