3 回答
![?](http://img1.sycdn.imooc.com/5458477300014deb02200220-100-100.jpg)
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)
![?](http://img1.sycdn.imooc.com/545869470001a00302200220-100-100.jpg)
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
}
![?](http://img1.sycdn.imooc.com/54584cd10001404b02200220-100-100.jpg)
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}]
没有找到匹配的内容?试试慕课网站内搜索吧
- 3 回答
- 0 关注
- 181 浏览
添加回答
举报