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

创建 goroutine 并设置最大 goroutine

创建 goroutine 并设置最大 goroutine

Go
牛魔王的故事 2023-06-26 17:12:44
我正在学习 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 的内容,但到目前为止我还没有了解。
查看完整描述

3 回答

?
喵喵时光机

TA贡献1846条经验 获得超7个赞

启动 20 个 goroutine 来完成工作。使用通道将工作分配给这些 goroutine。等待 goroutine 完成。


// c is channel for sending *Server values to worker goroutines.

c := make(chan *Server)


// Start worker goroutines. Each goroutine receives 

// values from c in a loop. The loop breaks when c

// is closed.

var wg sync.WaitGroup

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

    wg.Add(1)

    go func() {

       for server := range c {

           server.rtt = getRTT(server.ip)

       }

       wg.Done()

    }()

}


// Feed work to the goroutines.

for _, server := range servers {

    c <- server

}


// Close channel to cause workers to break out of 

// for loop.

close(c)


// Wait for the workers to complete.

wg.Wait()


fmt.Println(servers)


查看完整回答
反对 回复 2023-06-26
?
MM们

TA贡献1886条经验 获得超2个赞

Go 中有很多模式可以为 goroutine 设置阈值。我最喜欢的方法之一是使用管道。在管道模式中,您创建一组正在运行的 goroutine 并将结构传递给它们作为工作。

以下代码是管道的说明性示例。请注意,您必须提供一种同步方式来等待 goroutine 终止,例如使用sync.WaitGroup。

package main


import "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

}


查看完整回答
反对 回复 2023-06-26
?
30秒到达战场

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

我喜欢为此使用一个简单的计数信号量,并结合sync.WaitGroup来确保完成,正如@Parham Alvani建议的那样。(请注意,@Parham Alvani 的解决方案至少与此解决方案同样正确)

(一些解释 - 我们创建一个带有缓冲区的通道 - 缓冲区大小成为 goroutine 允许并发执行的数量。每个 goroutine 在通道中放入一些内容,然后将其读回。在下面的代码中,第五个有时,该 goroutine 会被阻塞添加到通道中,直到另一个 goroutine 从通道中取出某些内容。)

我还使用了“getRTT”函数来处理指向服务器的指针,因为我们在这里修改了接收器。

这里的游乐场: https ://play.golang.org/p/8Rmp0kHoNFB

package main


import (

    "fmt"

    "time"

    "sync"

    "math/rand"

)



type Server struct {

    id  uint

    ip  string

    rtt time.Duration

}



func (s *Server) setRTT()  {  

    fmt.Printf("setting rtt for id %d\n", s.id) 

    // do something that takes a while

    sleepyTime := time.Second * time.Duration(rand.Intn(5))

    time.Sleep(sleepyTime)

    s.rtt = sleepyTime

}


func main() {


    servers := []Server{

       {1,"10.10.10.0",0},

       {2,"10.10.10.1",0},

       {3,"10.10.10.2",0},

       {4,"10.10.10.3",0},

       {5,"10.10.10.4",0},

       {6,"10.10.10.5",0},

       {7,"10.10.10.0",0},

       {8,"10.10.10.1",0},

       {9,"10.10.10.2",0},

       {10,"10.10.10.3",0},

       {11,"10.10.10.4",0},

       {12,"10.10.10.5",0},

       {13,"10.10.10.0",0},

       {14,"10.10.10.1",0},

       {15,"10.10.10.2",0},

       {16,"10.10.10.3",0},


    }

    semaphore := make(chan struct{}, 4) // limit concurrency simply, you likely want a larger number than 4 here

    var wg sync.WaitGroup // necessary to ensure we complete everything - otherwise main will exit before we are done


    wg.Add(len(servers)) 


    for i := range servers {

        go func(s *Server) {

            defer wg.Done()

            semaphore <- struct{}{} // put something in channel, will block when > 4

            defer func() { <-semaphore }() // remove something from channel as this goroutine completes, allowing another goroutine to continue

            s.setRTT() 

        }(&servers[i])

    }

    wg.Wait() // wait for it!

    fmt.Println(servers)

}

示例输出:


setting rtt for id 16

setting rtt for id 1

setting rtt for id 2

setting rtt for id 3

setting rtt for id 4

setting rtt for id 5

setting rtt for id 6

setting rtt for id 7

setting rtt for id 8

setting rtt for id 9

setting rtt for id 10

setting rtt for id 11

setting rtt for id 12

setting rtt for id 13

setting rtt for id 14

setting 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}]



查看完整回答
反对 回复 2023-06-26
  • 3 回答
  • 0 关注
  • 128 浏览
慕课专栏
更多

添加回答

举报

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