Menu
Coddy logo textTech

Powtórka – pula workerów

Część sekcji Programowanie obiektowe ścieżki GO w Coddy. Lekcja 66 z 107.

challenge icon

Wyzwanie

Łatwy

Zbudujmy system przetwarzania zadań z użyciem wzorca puli pracowników! Utworzysz pulę pracowników, którzy będą równolegle przetwarzać zadania obliczeniowe, pokazując, jak kanały, goroutines i WaitGroups współpracują, aby wydajnie obsługiwać obciążenie.

Rozmieścisz swój kod w dwóch plikach:

  • pool.go: Zdefiniuj komponenty puli pracowników i jej logikę.

    Utwórz strukturę Task z polami ID (int) i Value (int), które będą reprezentować pracę do wykonania.

    Utwórz strukturę Result z polami TaskID (int) i Computed (int), które będą reprezentować wykonaną pracę.

    Zaimplementuj funkcję Worker, która przyjmuje identyfikator pracownika (int), kanał zadań tylko do odbioru (<-chan Task), kanał wyników tylko do wysyłania (chan<- Result) oraz wskaźnik na sync.WaitGroup. Każdy pracownik powinien:

    • Użyć defer wg.Done(), aby zasygnalizować zakończenie pracy
    • Iterować po kanale zadań, aby przetworzyć każde zadanie
    • Dla każdego zadania obliczyć kwadrat wartości Value tego zadania
    • Wysłać Result z TaskID i obliczonym kwadratem

    Zaimplementuj funkcję RunPool, która przyjmuje liczbę pracowników (int) oraz tablicę zadań. Funkcja powinna:

    • Utworzyć buforowane kanały zadań i wyników (użyć liczby zadań jako rozmiaru bufora)
    • Uruchomić określoną liczbę pracowników jako goroutines
    • Wysłać wszystkie zadania do kanału zadań, a następnie go zamknąć
    • Użyć goroutine z WaitGroup do zamknięcia kanału wyników po zakończeniu pracy wszystkich pracowników
    • Zebrać wszystkie wyniki do tablicy i ją zwrócić

  • main.go: Odczytaj dane wejściowe i koordynuj pulę pracowników.

    Odczytaj liczbę pracowników, a następnie liczbę zadań. Dla każdego zadania odczytaj jego identyfikator i wartość. Wywołaj RunPool, przekazując pracowników i zadania, a następnie wypisz każdy wynik w formacie: Task [TaskID]: [Computed]

    Wypisz wyniki posortowane rosnąco według TaskID.

Podane zostaną następujące dane wejściowe:

  • Wiersz 1: Liczba pracowników (liczba całkowita)
  • Wiersz 2: Liczba zadań (liczba całkowita)
  • Kolejne wiersze: Dla każdego zadania dwa wiersze — identyfikator zadania (liczba całkowita), a następnie jego wartość (liczba całkowita)

Na przykład dla danych:

2
4
1
3
2
5
3
2
4
7

Wynik powinien być następujący:

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

Pracownicy przetwarzają zadania równolegle (kwadrat liczby 3 to 9, kwadrat liczby 5 to 25 itd.), a wyniki są zbierane i wyświetlane w kolejności według identyfikatorów zadań. Przy 2 pracownikach obsługujących 4 zadania praca jest wydajnie rozdzielana w puli.

Spróbuj swoich sił

package main

import (
	"fmt"
	"sort"
)

func main() {
	// Wczytaj liczbę pracowników
	var numWorkers int
	fmt.Scanln(&numWorkers)

	// Wczytaj liczbę zadań
	var numTasks int
	fmt.Scanln(&numTasks)

	// Wczytaj zadania
	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: Wywołaj RunPool z pracownikami i zadaniami

	// TODO: Posortuj wyniki według TaskID w kolejności rosnącej

	// TODO: Wypisz każdy wynik w formacie: Task [TaskID]: [Computed]
}

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator Go online