私はGolangのforループを使って同時に1000個のゴルーチンを開始すると考えています。
問題は次のとおりです。すべてのgoroutineが実行されていることを確認する必要があります。
これを確認するのにチャンネルを使用することは可能ですか?Golangでは、チャンネルで多くのゴルーチンを扱う方法
構造はちょっと、このようなものです:
func main {
for i ... {
go ...
ch?
ch?
}
私はGolangのforループを使って同時に1000個のゴルーチンを開始すると考えています。
問題は次のとおりです。すべてのgoroutineが実行されていることを確認する必要があります。
これを確認するのにチャンネルを使用することは可能ですか?Golangでは、チャンネルで多くのゴルーチンを扱う方法
構造はちょっと、このようなものです:
func main {
for i ... {
go ...
ch?
ch?
}
はい、thisを試してみてください。
package main
import (
"fmt"
)
const max = 1000
func main() {
for i := 1; i <= max; i++ {
go f(i)
}
s := 0
for i := 1; i <= max; i++ {
s += <-ch
}
fmt.Println(s)
}
func f(n int) {
// do a job here
ch <- n
}
var ch = make(chan int, max)
出力:
500500
これは動作し、OPの制約を満たしていますが、これはベストプラクティスではありません。このアドホックなアプローチの問題は、保守性と拡張性です。 'WaitGroup'は、この正確な問題に取り組むために設計されました。 –
@KshitijSaraogi:ベストプラクティスは、手元の問題に非常に依存します。例:1000個のゴルーチンが特定の計算をしてからメインのゴルーチンに 'int'の結果を送る必要があると想像してください。これがベストプラクティスです。 –
@Andyあなたはこれを達成するためにsync.WaitGroup
を使用することができます述べたように。以下は例です。コードが自明であることを願っています。
package main
import (
"fmt"
"sync"
"time"
)
func dosomething(millisecs int64, wg *sync.WaitGroup) {
defer wg.Done()
duration := time.Duration(millisecs) * time.Millisecond
time.Sleep(duration)
fmt.Println("Function in background, duration:", duration)
}
func main() {
arr := []int64{200, 400, 150, 600}
var wg sync.WaitGroup
for _, n := range arr {
wg.Add(1)
go dosomething(n, &wg)
}
wg.Wait()
fmt.Println("Done")
}
おそらく、 'dosomething()'の開始時に 'woo.Done()'を延期することは、もっと慣れないでしょう。 – biosckon
私はあなたがパターンに従うことを示唆しています。並行性とチャネルは良いですが、悪い方法で使用すると、プログラムが予想よりも遅くなる可能性があります。複数のゴールールとチャネルを処理する簡単な方法は、ワーカー・プール・パターンによるものです。
は、この単純な例では、hereから取られ
// In this example we'll look at how to implement
// a _worker pool_ using goroutines and channels.
package main
import "fmt"
import "time"
// Here's the worker, of which we'll run several
// concurrent instances. These workers will receive
// work on the `jobs` channel and send the corresponding
// results on `results`. We'll sleep a second per job to
// simulate an expensive task.
func worker(id int, jobs <-chan int, results chan<- int) {
for j := range jobs {
fmt.Println("worker", id, "started job", j)
time.Sleep(time.Second)
fmt.Println("worker", id, "finished job", j)
results <- j * 2
}
}
func main() {
// In order to use our pool of workers we need to send
// them work and collect their results. We make 2
// channels for this.
jobs := make(chan int, 100)
results := make(chan int, 100)
// This starts up 3 workers, initially blocked
// because there are no jobs yet.
for w := 1; w <= 3; w++ {
go worker(w, jobs, results)
}
// Here we send 5 `jobs` and then `close` that
// channel to indicate that's all the work we have.
for j := 1; j <= 5; j++ {
jobs <- j
}
close(jobs)
// Finally we collect all the results of the work.
for a := 1; a <= 5; a++ {
<-results
}
}
以下のコードをよく見てください。また、results
チャネルは、障害通知などのジョブを実行しているすべてのgoルーチンを追跡するのに役立ちます。
あなたはゴルーチンが終了するのを待っていますか?もしそうなら、 'sync.WaitGroup'を使うことができます。 https://golang.org/pkg/sync/#WaitGroupを参照してください。 –
私はこの仕事を理解していないかもしれません。 1000種類の異なるゴルーチンがありますか?そうでない場合、同じタスクを実行すると、どのアプリケーションが実行されたのかは異なりますか? –