Пул должен владеть фиксированными работниками и очередью заданий. В main нужно дождаться его завершения после окончания генератора, иначе процесс выйдет с незавершёнными запросами.
Конструирование пула воркеров
Пул должен владеть фиксированными работниками и очередью заданий. В main нужно дождаться его завершения после окончания генератора, иначе процесс выйдет с незавершёнными запросами.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Необходимо построить механизм, который:
- Запускает не более трёх воркеров одновременно;
- Делает HTTP GET запросы к каждому адресу из предоставленного списка;
- Ограничивает количество параллельных запросов, чтобы не перегрузить систему.
package main
import {
"log"
}
func main() {
pool :=makePool(3)
for url := range generateUrls(5){
log.Printf("=> Запуск, %s", url)
pool.Dowork(url)
}
}
Ответ
Пул должен владеть фиксированными работниками и очередью заданий. В main нужно дождаться его завершения после окончания генератора, иначе процесс выйдет с незавершёнными запросами.
Исправьте import на круглые скобки и добавьте net/http, sync, time. Минимальная реализация:
type Pool struct {
jobs chan string
wg sync.WaitGroup
client *http.Client
}
func makePool(n int) *Pool {
if n < 1 { panic("invalid workers") }
p := &Pool{jobs: make(chan string), client: &http.Client{Timeout: 5*time.Second}}
for i := 0; i < n; i++ {
p.wg.Add(1)
go func() {
defer p.wg.Done()
for url := range p.jobs {
resp, err := p.client.Get(url)
if err != nil { log.Printf("%s: %v", url, err); continue }
log.Printf("%s: %d", url, resp.StatusCode)
resp.Body.Close()
}
}()
}
return p
}
func (p *Pool) Dowork(url string) { p.jobs <- url }
func (p *Pool) Close() { close(p.jobs); p.wg.Wait() }
Сразу после makePool(3) поставьте defer pool.Close(). Close — однократная операция владельца после завершения всех отправок; конкурентно с Dowork его не вызывают. generateUrls должна закрыть выходной канал.