Go за Прикладом: Worker Pools

Розглянемо реалізацію шаблону worker pools використовуючи горутини та канали. Вільний переклад “wooker pools” українською “фонд робочої сили”, але оригінальний термін вживається частіше

package main
import (
    "fmt"
    "time"
)

Ось приклад, функції-робітника, якою ми скористаємось, щоб запустити кілька різних екземплярів робітників. Вони будуть отримувати роботу на каналі jobs і надсилати сповіщення про завершення роботи до каналу results. Роботою нашого “працівника” буде “сон довжиною в секунду” (така собі симуляція реальної роботи).

func worker(id int, jobs <-chan int, results chan<- int) {
    for j := range jobs {
        fmt.Println("працівник", id, "почав проботу", j)
        time.Sleep(time.Second)
        fmt.Println("працівник", id, "закінчив роботу", j)
        results <- j * 2
    }
}
func main() {

Щоб скористатись “worker pool” нам необхідно створити два канали: в один будемо передавати завдання робітнику, а з іншого отримувати результати роботи.

    const numJobs = 5
    jobs := make(chan int, numJobs)
    results := make(chan int, numJobs)

Спершу - запускаємо 3 функції-працівника, які блокуватимуться під час виконання (тому що жодної роботи для них поки що існує).

    for w := 1; w <= 3; w++ {
        go worker(w, jobs, results)
    }

Далі - Надішлемо 5 завдань до каналу роботи, після чого закриває канал щоб вказати що це вся робота що, наразі, доступна.

    for j := 1; j <= numJobs; j++ {
        jobs <- j
    }
    close(jobs)

І, нарешті, отримуємо результати роботи наших працівників.

    for a := 1; a <= numJobs; a++ {
        <-results
    }
}

Наша програма покаже 5 завдань - що виконуються різними працівниками. Програма працює близько 2 секунд, не зважаючи на роботу розраховану вцілому на 5 секунд - і все це завдяки 3’ом працівникам, що працюються одночасно.

$ time go run worker-pools.go
працівник 1 почав проботу над завданням 2
працівник 3 почав проботу над завданням 1
працівник 2 почав проботу над завданням 3
працівник 1 закінчив роботу над завданням 2
працівник 3 закінчив роботу над завданням 1
працівник 3 почав проботу над завданням 5
працівник 2 закінчив роботу над завданням 3
працівник 1 почав проботу над завданням 4
працівник 1 закінчив роботу над завданням 4
працівник 3 закінчив роботу над завданням 5
real    0m2.322s
user    0m0.231s
sys    0m0.290s

Наступний приклад: Обмеження Частоти Запитів.