Bounded Parallelism: ограниченное число воркеров
Условие задачи
У тебя есть 100 задач, каждая занимает около 100 миллисекунд. Нужно обработать их с максимальной эффективностью, но не запускать более 10 задач одновременно. Реализуй worker pool с ограничением по количеству параллельных задач.
package main
import (
"fmt"
"time"
)
func doWork(id int) {
time.Sleep(100 * time.Millisecond)
fmt.Println("done", id)
}
func main() {
// TODO: реализуй обработку 100 задач с ограничением на 10 параллельных
}
package main
import (
"fmt"
"time"
)
func doWork(id int) {
time.Sleep(100 * time.Millisecond)
fmt.Println("done", id)
}
func main() {
// TODO: реализуй обработку 100 задач с ограничением на 10 параллельных
}
Подсказка
- Используй семафор на основе буферизованного канала. - Можно также использовать фиксированный pool горутин и канал задач. - Не забудь дождаться завершения всех задач.
Решение
Bounded Parallelism позволяет контролировать нагрузку, не создавая слишком много горутин. Это часто применяется при работе с БД, сетью, API.
package main
import (
"fmt"
"sync"
"time"
)
func doWork(id int) {
time.Sleep(100 * time.Millisecond)
fmt.Println("done", id)
}
func main() {
var wg sync.WaitGroup
sem := make(chan struct{}, 10)
for i := 0; i < 100; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
sem <- struct{}{}
doWork(id)
<-sem
}(i)
}
wg.Wait()
}
package main
import (
"fmt"
"sync"
"time"
)
func doWork(id int) {
time.Sleep(100 * time.Millisecond)
fmt.Println("done", id)
}
func main() {
var wg sync.WaitGroup
sem := make(chan struct{}, 10)
for i := 0; i < 100; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
sem <- struct{}{}
doWork(id)
<-sem
}(i)
}
wg.Wait()
}