创建 goroutine 并设置最大 goroutine

我正在学习 Golang,但遇到了一些困难。我已经研究过谷歌,但没有进展。


我编写了一个代码,通过多个服务器的 ICMP 检查 RTT。


它有这样的结构:


type Server struct {

    id  uint

    ip  string

    rtt time.Duration

}

它有一个包含多个服务器的切片(它是一个数组吗?)。对于此切片中的每个服务器,我调用返回 RTT 的函数 getRTT,然后将其存储在其中,Server.rtt因为在 for 循环之后,我想打印所有服务器及其各自的 RTT。


for _, server := range servers {

    server.rtt = getRTT(server.ip) / time.Millisecond

}

fmt.Println(servers)

问题是同步,所以一一发送“ping”。我想让这个异步并限制最大 goroutine。示例:一次调用 20 个 getRTT。


我正在阅读有关 goroutine、maxgroup、channel 的内容,但到目前为止我还没有了解。


牛魔王的故事
浏览 182回答 3
3回答

喵喵时光机

启动 20 个 goroutine 来完成工作。使用通道将工作分配给这些 goroutine。等待 goroutine 完成。// c is channel for sending *Server values to worker goroutines.c := make(chan *Server)// Start worker goroutines. Each goroutine receives&nbsp;// values from c in a loop. The loop breaks when c// is closed.var wg sync.WaitGroupfor i := 0; i < 20; i++ {&nbsp; &nbsp; wg.Add(1)&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp;for server := range c {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;server.rtt = getRTT(server.ip)&nbsp; &nbsp; &nbsp; &nbsp;}&nbsp; &nbsp; &nbsp; &nbsp;wg.Done()&nbsp; &nbsp; }()}// Feed work to the goroutines.for _, server := range servers {&nbsp; &nbsp; c <- server}// Close channel to cause workers to break out of&nbsp;// for loop.close(c)// Wait for the workers to complete.wg.Wait()fmt.Println(servers)

MM们

Go 中有很多模式可以为 goroutine 设置阈值。我最喜欢的方法之一是使用管道。在管道模式中,您创建一组正在运行的 goroutine 并将结构传递给它们作为工作。以下代码是管道的说明性示例。请注意,您必须提供一种同步方式来等待 goroutine 终止,例如使用sync.WaitGroup。package mainimport "fmt"type handler struct {        workStream chan int}func (h handler) handle() {        for w := range h.workStream {                fmt.Printf("do some work with %d\n", w)        }}func main() {        h := handler{                workStream: make(chan int),        }        // run goroutines as much as you want        for i := 0; i < 5; i++ {                go h.handle()        }        for i := 0; i < 1000; i++ {                h.workStream <- i        }        close(h.workStream) // by closing this channel all goroutines all killed        // TODO: wait for all goroutines to die}

30秒到达战场

我喜欢为此使用一个简单的计数信号量,并结合sync.WaitGroup来确保完成,正如@Parham Alvani建议的那样。(请注意,@Parham Alvani 的解决方案至少与此解决方案同样正确)(一些解释 - 我们创建一个带有缓冲区的通道 - 缓冲区大小成为 goroutine 允许并发执行的数量。每个 goroutine 在通道中放入一些内容,然后将其读回。在下面的代码中,第五个有时,该 goroutine 会被阻塞添加到通道中,直到另一个 goroutine 从通道中取出某些内容。)我还使用了“getRTT”函数来处理指向服务器的指针,因为我们在这里修改了接收器。这里的游乐场:&nbsp;https ://play.golang.org/p/8Rmp0kHoNFBpackage mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "time"&nbsp; &nbsp; "sync"&nbsp; &nbsp; "math/rand")type Server struct {&nbsp; &nbsp; id&nbsp; uint&nbsp; &nbsp; ip&nbsp; string&nbsp; &nbsp; rtt time.Duration}func (s *Server) setRTT()&nbsp; {&nbsp;&nbsp;&nbsp; &nbsp; fmt.Printf("setting rtt for id %d\n", s.id)&nbsp;&nbsp; &nbsp; // do something that takes a while&nbsp; &nbsp; sleepyTime := time.Second * time.Duration(rand.Intn(5))&nbsp; &nbsp; time.Sleep(sleepyTime)&nbsp; &nbsp; s.rtt = sleepyTime}func main() {&nbsp; &nbsp; servers := []Server{&nbsp; &nbsp; &nbsp; &nbsp;{1,"10.10.10.0",0},&nbsp; &nbsp; &nbsp; &nbsp;{2,"10.10.10.1",0},&nbsp; &nbsp; &nbsp; &nbsp;{3,"10.10.10.2",0},&nbsp; &nbsp; &nbsp; &nbsp;{4,"10.10.10.3",0},&nbsp; &nbsp; &nbsp; &nbsp;{5,"10.10.10.4",0},&nbsp; &nbsp; &nbsp; &nbsp;{6,"10.10.10.5",0},&nbsp; &nbsp; &nbsp; &nbsp;{7,"10.10.10.0",0},&nbsp; &nbsp; &nbsp; &nbsp;{8,"10.10.10.1",0},&nbsp; &nbsp; &nbsp; &nbsp;{9,"10.10.10.2",0},&nbsp; &nbsp; &nbsp; &nbsp;{10,"10.10.10.3",0},&nbsp; &nbsp; &nbsp; &nbsp;{11,"10.10.10.4",0},&nbsp; &nbsp; &nbsp; &nbsp;{12,"10.10.10.5",0},&nbsp; &nbsp; &nbsp; &nbsp;{13,"10.10.10.0",0},&nbsp; &nbsp; &nbsp; &nbsp;{14,"10.10.10.1",0},&nbsp; &nbsp; &nbsp; &nbsp;{15,"10.10.10.2",0},&nbsp; &nbsp; &nbsp; &nbsp;{16,"10.10.10.3",0},&nbsp; &nbsp; }&nbsp; &nbsp; semaphore := make(chan struct{}, 4) // limit concurrency simply, you likely want a larger number than 4 here&nbsp; &nbsp; var wg sync.WaitGroup // necessary to ensure we complete everything - otherwise main will exit before we are done&nbsp; &nbsp; wg.Add(len(servers))&nbsp;&nbsp; &nbsp; for i := range servers {&nbsp; &nbsp; &nbsp; &nbsp; go func(s *Server) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; defer wg.Done()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; semaphore <- struct{}{} // put something in channel, will block when > 4&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; defer func() { <-semaphore }() // remove something from channel as this goroutine completes, allowing another goroutine to continue&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; s.setRTT()&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; }(&servers[i])&nbsp; &nbsp; }&nbsp; &nbsp; wg.Wait() // wait for it!&nbsp; &nbsp; fmt.Println(servers)}示例输出:setting rtt for id 16setting rtt for id 1setting rtt for id 2setting rtt for id 3setting rtt for id 4setting rtt for id 5setting rtt for id 6setting rtt for id 7setting rtt for id 8setting rtt for id 9setting rtt for id 10setting rtt for id 11setting rtt for id 12setting rtt for id 13setting rtt for id 14setting rtt for id 15[{1 10.10.10.0 2000000000} {2 10.10.10.1 2000000000} {3 10.10.10.2 4000000000} {4 10.10.10.3 1000000000} {5 10.10.10.4 3000000000} {6 10.10.10.5 0} {7 10.10.10.0 0} {8 10.10.10.1 1000000000} {9 10.10.10.2 0} {10 10.10.10.3 4000000000} {11 10.10.10.4 1000000000} {12 10.10.10.5 2000000000} {13 10.10.10.0 4000000000} {14 10.10.10.1 3000000000} {15 10.10.10.2 4000000000} {16 10.10.10.3 1000000000}]
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go