第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問(wèn)題,去搜搜看,總會(huì)有你想問(wèn)的

是否可以取消未完成的 goroutines?

是否可以取消未完成的 goroutines?

Go
九州編程 2022-11-28 17:15:08
考慮一組檢查工作,每個(gè)檢查工作都有獨(dú)立的邏輯,因此它們似乎可以并發(fā)運(yùn)行,例如:type Work struct {    // ...}// This Check could be quite time-consumingfunc (w *Work) Check() bool {    // return succeed or not    //...}func CheckAll(works []*Work) {    num := len(works)    results := make(chan bool, num)    for _, w := range works {        go func(w *Work) {            results <- w.Check()        }(w)    }    for i := 0; i < num; i++ {        if r := <-results; !r {            ReportFailed()            break;        }    }}func ReportFailed() {    // ...}在關(guān)注 的時(shí)候results,如果邏輯是無(wú)論哪個(gè)工作失敗,我們斷言所有工作都完全失敗,通道中剩余的值是無(wú)用的。讓剩余未完成的 goroutines 繼續(xù)運(yùn)行并將結(jié)果發(fā)送到通道是沒(méi)有意義和浪費(fèi)的,尤其是在w.Check()相當(dāng)耗時(shí)的情況下。理想效果類似于:    for _, w := range works {        if !w.Check() {            ReportFailed()            break;        }    }這只運(yùn)行必要的檢查工作然后中斷,但在順序非并發(fā)場(chǎng)景中。那么,是否可以取消這些未完成的goroutines,或者發(fā)送到channel?
查看完整描述

3 回答

?
嗶嗶one

TA貢獻(xiàn)1854條經(jīng)驗(yàn) 獲得超8個(gè)贊

取消(阻塞)發(fā)送

您最初的問(wèn)題詢問(wèn)如何取消發(fā)送操作。頻道上的發(fā)送基本上是“即時(shí)的”。如果通道的緩沖區(qū)已滿并且沒(méi)有準(zhǔn)備好的接收器,則通道上的發(fā)送會(huì)阻塞。


您可以使用select聲明和cancel您關(guān)閉的頻道“取消”此發(fā)送,例如:


cancel := make(chan struct{})


select {

case ch <- value:

case <- cancel:

}

在另一個(gè) goroutine 上關(guān)閉cancel通道close(cancel)將使上面的選擇放棄發(fā)送ch(如果它正在阻塞)。


但如前所述,發(fā)送在“就緒”通道上是“即時(shí)的”,并且發(fā)送首先評(píng)估要發(fā)送的值:


results <- w.Check()

這首先必須運(yùn)行w.Check(),一旦完成,它的返回值將在 上發(fā)送results。


取消函數(shù)調(diào)用

所以你真正需要的是取消w.Check()方法調(diào)用。為此,慣用的方法是傳遞一個(gè)context.Context可以取消的值,它w.Check()本身必須監(jiān)視并“服從”這個(gè)取消請(qǐng)求。


請(qǐng)參見(jiàn)在取消上下文時(shí)終止函數(shù)執(zhí)行

請(qǐng)注意,您的函數(shù)必須明確支持這一點(diǎn)。沒(méi)有函數(shù)調(diào)用或 goroutines 的隱式終止,請(qǐng)參閱取消 Go 中的阻塞操作。


所以你Check()應(yīng)該看起來(lái)像這樣:


// This Check could be quite time-consuming

func (w *Work) Check(ctx context.Context, workDuration time.Duration) bool {

    // Do your thing and monitor the context!


    select {

    case <-ctx.Done():

        return false

    case <-time.After(workDuration): // Simulate work

        return true

    case <-time.After(2500 * time.Millisecond): // Simulate failure after 2.5 sec

        return false

    }

}

CheckAll()可能看起來(lái)像這樣:


func CheckAll(works []*Work) {

    ctx, cancel := context.WithCancel(context.Background())

    defer cancel()


    num := len(works)

    results := make(chan bool, num)


    wg := &sync.WaitGroup{}

    for i, w := range works {

        workDuration := time.Second * time.Duration(i)

        wg.Add(1)

        go func(w *Work) {

            defer wg.Done()

            result := w.Check(ctx, workDuration)

            // You may check and return if context is cancelled

            // so result is surely not sent, I omitted it here.

            select {

            case results <- result:

            case <-ctx.Done():

                return

            }

        }(w)

    }


    go func() {

        wg.Wait()

        close(results) // This allows the for range over results to terminate

    }()


    for result := range results {

        fmt.Println("Result:", result)

        if !result {

            cancel()

            break

        }

    }

}

測(cè)試它:


CheckAll(make([]*Work, 10))

輸出(在Go Playground上嘗試):


Result: true

Result: true

Result: true

Result: false

我們true打印了 3 次(工作在 2.5 秒內(nèi)完成),然后故障模擬開(kāi)始,返回false并終止所有其他工作。


請(qǐng)注意,sync.WaitGroup上面示例中的 并不是嚴(yán)格需要的,因?yàn)閞esults它有一個(gè)能夠保存所有結(jié)果的緩沖區(qū),但總的來(lái)說(shuō)它仍然是一個(gè)很好的做法(如果您將來(lái)使用較小的緩沖區(qū))。


查看完整回答
反對(duì) 回復(fù) 2022-11-28
?
料青山看我應(yīng)如是

TA貢獻(xiàn)1772條經(jīng)驗(yàn) 獲得超8個(gè)贊

簡(jiǎn)短的回答是:

return除非 goroutine 本身到達(dá)其堆棧的末尾,否則您不能取消或關(guān)閉任何 goroutine 。

如果你想取消某些東西,最好的方法是將 a 傳遞給它們并在例程中context.Context收聽(tīng)它。context.Done()每當(dāng)上下文被取消時(shí),你應(yīng)該return在執(zhí)行 defers(如果有的話)后 goroutine 會(huì)自動(dòng)死掉。


查看完整回答
反對(duì) 回復(fù) 2022-11-28
?
鳳凰求蠱

TA貢獻(xiàn)1825條經(jīng)驗(yàn) 獲得超4個(gè)贊

package main


import "fmt"


type Work struct {

    // ...

    Name string

    IsSuccess chan bool

}


// This Check could be quite time-consuming

func (w *Work) Check() {

    // return succeed or not


    //...

    if len(w.Name) > 0 {

        w.IsSuccess <- true

    }else{

        w.IsSuccess <- false

    }


}



//堆排序

func main() {

    works := make([]*Work,3)

    works[0] = &Work{

        Name: "",

        IsSuccess: make(chan bool),

    }

    works[1] =  &Work{

        Name: "111",

        IsSuccess: make(chan bool),

    }

    works[2] =&Work{

        Name: "",

        IsSuccess: make(chan bool),

    }


    for _,w := range works {

        go w.Check()

    }


    for i,w := range works{

        select {

        case checkResult := <-w.IsSuccess :

            fmt.Printf("index %d checkresult %t \n",i,checkResult)

        }

    }

}

在此處輸入圖像描述


查看完整回答
反對(duì) 回復(fù) 2022-11-28
  • 3 回答
  • 0 關(guān)注
  • 135 瀏覽
慕課專欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)