3 回答

TA貢獻1846條經(jīng)驗 獲得超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)

TA貢獻1886條經(jīng)驗 獲得超2個贊
Go 中有很多模式可以為 goroutine 設(shè)置閾值。我最喜歡的方法之一是使用管道。在管道模式中,您創(chuàng)建一組正在運行的 goroutine 并將結(jié)構(gòu)傳遞給它們作為工作。
以下代碼是管道的說明性示例。請注意,您必須提供一種同步方式來等待 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
}

TA貢獻1828條經(jīng)驗 獲得超6個贊
我喜歡為此使用一個簡單的計數(shù)信號量,并結(jié)合sync.WaitGroup來確保完成,正如@Parham Alvani建議的那樣。(請注意,@Parham Alvani 的解決方案至少與此解決方案同樣正確)
(一些解釋 - 我們創(chuàng)建一個帶有緩沖區(qū)的通道 - 緩沖區(qū)大小成為 goroutine 允許并發(fā)執(zhí)行的數(shù)量。每個 goroutine 在通道中放入一些內(nèi)容,然后將其讀回。在下面的代碼中,第五個有時,該 goroutine 會被阻塞添加到通道中,直到另一個 goroutine 從通道中取出某些內(nèi)容。)
我還使用了“getRTT”函數(shù)來處理指向服務器的指針,因為我們在這里修改了接收器。
這里的游樂場: 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 關(guān)注
- 216 瀏覽
添加回答
舉報