golangで並行数を管理する方法
Goでは、goroutineとchannelを利用して排他制御することができます。
まず、make関数を使用して指定した同時実行数を持ったチャネルを作成できます。例えば、同時実行数を10に制御したい場合は、バッファーのないチャネルを10個作成できます。
concurrency := 10
ch := make(chan struct{}, concurrency)
コンカレンシーを制御するべき場所では、各タスクを実行する前に空の`struct {}`値をチャンネルに送信してコンカレンシーの空きスロットを占有し、コンカレンシータスクの開始を表します。タスクが完了したら、チャンネルから値を受信してコンカレンシーの空きスロットを解放します。
ch <- struct{}{} // 占用一个并发槽
go func() {
defer func() { <-ch }() // 释放一个并发槽
// 执行并发任务的代码
}()
チャンネルの送受信を制御することで同時に実行される並列タスクの数を制御できます。
完全なコードの例は以下の通りです。
package main
import (
"fmt"
"time"
)
func main() {
concurrency := 10
ch := make(chan struct{}, concurrency)
tasks := []string{"task1", "task2", "task3", "task4", "task5", "task6", "task7", "task8", "task9", "task10"}
for _, task := range tasks {
ch <- struct{}{} // 占用一个并发槽
go func(t string) {
defer func() { <-ch }() // 释放一个并发槽
fmt.Printf("开始执行任务:%s\n", t)
time.Sleep(time.Second) // 模拟任务的耗时
fmt.Printf("任务:%s 执行完成\n", t)
}(task)
}
// 等待所有任务完成
for i := 0; i < concurrency; i++ {
ch <- struct{}{}
}
}
上記のサンプルでは、10のコンカレントスロットを持つチャネルを作成してから、goroutineを使用してタスクを実行しました。各タスクの開始時と終了時に、対応するログを出力します。最後に、すべてのタスクが完了するのを待つために、forループを使います。
最終の for ループで空構造体 {} をさらに 10 個チャネルに送信し、すべての goroutine が完了するのを確実にします。これにより、すべての並列スロットが解放されます。
チャンネルで同時実行数を制御することができます。