为了账号安全,请及时绑定邮箱和手机立即绑定

使用sync.WaitGroup.wait时如何实现超时?

使用sync.WaitGroup.wait时如何实现超时?

Go
慕娘9325324 2021-11-29 16:52:45
我遇到过一种情况,我想跟踪某个 goroutine 以在特定点上进行同步,例如在获取所有 url 时。然后,我们可以将它们全部放置并按特定顺序显示。我认为这是障碍进来的。它是在go与sync.WaitGroup. 但是,在实际情况下,我们无法确保所有的 fetch 操作都会在短时间内成功。所以,我想wait在获取操作时引入超时。我是新手Golang,所以有人可以给我一些建议吗?我正在寻找的是这样的:   wg := &sync.WaigGroup{}   select {   case <-wg.Wait():   // All done!   case <-time.After(500 * time.Millisecond):   // Hit timeout.   }我知道Wait不支持Channel。
查看完整描述

3 回答

?
慕桂英4014372

TA贡献1871条经验 获得超13个赞

如果你想要的只是你的简洁选择,你可以通过生成一个调用方法并在完成后关闭/发送通道的例程来轻松地将阻塞功能转换为通道。


done := make(chan struct{})

go func() {

   wg.Wait()

   close(done)

}()


select {

case <-done:

// All done!

case <-time.After(500 * time.Millisecond):

// Hit timeout.

}


查看完整回答
反对 回复 2021-11-29
?
慕尼黑的夜晚无繁华

TA贡献1864条经验 获得超6个赞

将您的结果发送到一个缓冲通道,足以获取所有结果,而不会阻塞,并在主线程的 for-select 循环中读取它们:


func work(msg string, d time.Duration, ret chan<- string) {

    time.Sleep(d) // Work emulation.

    select {

    case ret <- msg:

    default:

    }

}


// ...


const N = 2

ch := make(chan string, N)


go work("printed", 100*time.Millisecond, ch)

go work("not printed", 1000*time.Millisecond, ch)


timeout := time.After(500 * time.Millisecond)

loop:

for received := 0; received < N; received++ {

    select {

    case msg := <-ch:

        fmt.Println(msg)

    case <-timeout:

        fmt.Println("timeout!")

        break loop

    }

}

游乐场:http : //play.golang.org/p/PxeEEJo2dz。


查看完整回答
反对 回复 2021-11-29
?
慕标5832272

TA贡献1966条经验 获得超4个赞

另一种方法是在内部对其进行监控,您的问题是有限的,但我假设您正在通过循环启动 goroutines,即使您不是,您也可以重构它来为您工作,但您可以这样做这两个示例之一,第一个将超时每个请求单独超时,第二个将超时整批请求,如果时间过长则继续


var wg sync.WaitGroup

wg.Add(1)

go func() {

    success := make(chan struct{}, 1)

    go func() {

        // send your request and wait for a response

        // pretend response was received

        time.Sleep(5 * time.Second)

        success <- struct{}{}

        // goroutine will close gracefully after return     

        fmt.Println("Returned Gracefully")

    }()


    select {

    case <-success:

        break

    case <-time.After(1 * time.Second):

        break

    }


    wg.Done()

    // everything should be garbage collected and no longer take up space

}()


wg.Wait()


// do whatever with what you got    

fmt.Println("Done")

time.Sleep(10 * time.Second)

fmt.Println("Checking to make sure nothing throws errors after limbo goroutine is done")

或者,如果您只是想要一个通用的简单方法来超时所有请求,您可以执行以下操作


var wg sync.WaitGroup

waiter := make(chan int)

wg.Add(1)

go func() {

    success := make(chan struct{}, 1)

    go func() {

        // send your request and wait for a response

        // pretend response was received

        time.Sleep(5 * time.Second)

        success <- struct{}{}

        // goroutine will close gracefully after return     

        fmt.Println("Returned Gracefully")

    }()


    select {

    case <-success:

        break

    case <-time.After(1 * time.Second):

        // control the timeouts for each request individually to make sure that wg.Done gets called and will let the goroutine holding the .Wait close

        break

    }

    wg.Done()

    // everything should be garbage collected and no longer take up space

}()


completed := false

go func(completed *bool) {

    // Unblock with either wait

    wg.Wait()

    if !*completed {

        waiter <- 1         

        *completed = true

    }       

    fmt.Println("Returned Two")

}(&completed)


go func(completed *bool) {

    // wait however long

    time.Sleep(time.Second * 5)

    if !*completed {

        waiter <- 1         

        *completed = true

    }       

    fmt.Println("Returned One")

}(&completed)



 // block until it either times out or .Wait stops blocking 

 <-waiter


// do whatever with what you got    

fmt.Println("Done")

time.Sleep(10 * time.Second)

fmt.Println("Checking to make sure nothing throws errors after limbo goroutine is done")

这样你的 WaitGroup 将保持同步,你不会有任何 goroutines 处于不确定状态


http://play.golang.org/p/g0J_qJ1BUT在这里试试你可以改变周围的变量以查看它的工作方式不同


编辑:我在移动设备上如果有人可以修复格式,那将是非常感谢。


查看完整回答
反对 回复 2021-11-29
  • 3 回答
  • 0 关注
  • 350 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信