Menu
Coddy logo textTech

Повторение — Worker Pool

Часть раздела Объектно-ориентированное программирование путешествия по GO на Coddy — урок 66 из 107.

challenge icon

Задание

Легко

Давайте создадим систему обработки задач, используя паттерн "пул воркеров" (worker pool)! Вы создадите пул воркеров, которые одновременно обрабатывают вычислительные задачи, демонстрируя, как каналы, горутины и WaitGroups работают вместе для эффективной обработки рабочих нагрузок.

Вы организуете свой код в двух файлах:

  • pool.go: Определите компоненты и логику вашего пула воркеров.

    Создайте структуру Task с полями ID (int) и Value (int), представляющими работу, которую необходимо выполнить.

    Создайте структуру Result с полями TaskID (int) и Computed (int), представляющими завершенную работу.

    Реализуйте функцию Worker, которая принимает ID воркера (int), канал задач только для чтения (<-chan Task), канал для результатов только для записи (chan<- Result) и указатель на sync.WaitGroup. Каждый воркер должен:

    • Использовать defer wg.Done() для сигнализации о завершении
    • Итерироваться (range) по каналу задач для обработки каждой задачи
    • Для каждой задачи вычислить квадрат значения Value
    • Отправить Result с TaskID и вычисленным квадратом

    Реализуйте функцию RunPool, которая принимает количество воркеров (int) и срез задач. Эта функция должна:

    • Создать буферизованные каналы для задач и результатов (используйте количество задач в качестве размера буфера)
    • Запустить указанное количество воркеров в виде горутин
    • Отправить все задачи в канал задач, а затем закрыть его
    • Использовать горутину с WaitGroup, чтобы закрыть канал результатов после того, как все воркеры закончат работу
    • Собрать все результаты в срез и вернуть его

  • main.go: Чтение входных данных и координация пула воркеров.

    Прочитайте количество воркеров, затем количество задач. Для каждой задачи прочитайте её ID и значение. Вызовите RunPool с воркерами и задачами, затем выведите каждый результат в формате: Task [TaskID]: [Computed]

    Выведите результаты, отсортированные по TaskID в порядке возрастания.

Будут предоставлены следующие входные данные:

  • Строка 1: Количество воркеров (целое число)
  • Строка 2: Количество задач (целое число)
  • Следующие строки: Для каждой задачи две строки — ID задачи (целое число), затем её значение (целое число)

Например, при вводе:

2
4
1
3
2
5
3
2
4
7

Ваш вывод должен быть:

Task 1: 9
Task 2: 25
Task 3: 4
Task 4: 49

Воркеры обрабатывают задачи параллельно (3 в квадрате — 9, 5 в квадрате — 25 и т. д.), а результаты собираются и отображаются по порядку ID задач. С 2 воркерами, обрабатывающими 4 задачи, работа эффективно распределяется по пулу.

Попробуйте сами

package main

import (
	"fmt"
	"sort"
)

func main() {
	// Считать количество рабочих
	var numWorkers int
	fmt.Scanln(&numWorkers)

	// Считать количество задач
	var numTasks int
	fmt.Scanln(&numTasks)

	// Считать задачи
	tasks := make([]Task, numTasks)
	for i := 0; i < numTasks; i++ {
		var id, value int
		fmt.Scanln(&id)
		fmt.Scanln(&value)
		tasks[i] = Task{ID: id, Value: value}
	}

	// TODO: Вызвать RunPool с рабочими и задачами

	// TODO: Отсортировать результаты по TaskID в порядке возрастания

	// TODO: Вывести каждый результат в формате: Task [TaskID]: [Computed]
}

Все уроки раздела Объектно-ориентированное программирование