Menu
Coddy logo textTech

まとめ - Worker Pool

CoddyのGOジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 66/107。

challenge icon

チャレンジ

簡単

ワーカープールパターンを使用してタスク処理システムを構築しましょう!並行して計算タスクを処理するワーカーのプールを作成し、チャネル、ゴルーチン、および WaitGroup がどのように連携してワークロードを効率的に処理するかを実証します。

コードは2つのファイルに分けて構成します:

  • pool.go: ワーカープールのコンポーネントとロジックを定義します。

    実行すべき作業を表す ID (int) と Value (int) フィールドを持つ Task 構造体を作成します。

    完了した作業を表す TaskID (int) と Computed (int) フィールドを持つ Result 構造体を作成します。

    ワーカー ID (int)、タスクの受信専用チャネル (<-chan Task)、結果の送信専用チャネル (chan<- Result)、および sync.WaitGroup へのポインタを受け取る Worker 関数を実装します。各ワーカーは以下を行う必要があります:

    • defer wg.Done() を使用して完了を通知する
    • tasks チャネルを range で回して各タスクを処理する
    • 各タスクについて、タスクの Value の2乗を計算する
    • TaskID と計算された2乗の値を含む Result を送信する

    ワーカー数 (int) とタスクのスライスを受け取る RunPool 関数を実装します。この関数は以下を行う必要があります:

    • タスク用と結果用のバッファ付きチャネルを作成する(バッファサイズとしてタスクの数を使用する)
    • 指定された数のワーカーをゴルーチンとして起動する
    • すべてのタスクを tasks チャネルに送信し、その後チャネルを閉じる
    • すべてのワーカーが終了した後に results チャネルを閉じるために、WaitGroup を使用したゴルーチンを使用する
    • すべての結果をスライスに収集して返す

  • main.go: 入力を読み取り、ワーカープールを調整します。

    ワーカー数、次にタスク数を読み取ります。各タスクについて、その ID と値を読み取ります。ワーカーとタスクを指定して RunPool を呼び出し、各結果を Task [TaskID]: [Computed] の形式で出力します。

    結果は TaskID の昇順でソートして出力してください。

以下の入力が提供されます:

  • 1行目:ワーカー数(整数)
  • 2行目:タスク数(整数)
  • 続く行:各タスクについて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の2乗は9、5の2乗は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]」の形式で出力する
}

オブジェクト指向プログラミングのすべてのレッスン