Dev Study
← 解説「thread::spawn — スレッドを起動する」に戻る

サンプルコードで身につける: thread::spawn — スレッドを起動する

解説で学んだ概念を、5つの具体例で確認します。素朴な例から実務寄りの例へと進みます。

1最小の spawn — 起動して join で待つ

thread::spawn にクロージャを渡すと別スレッドで動き、handle.join() で完了を待って返り値を受け取れる、最小の往復です。spawn した直後にメインはもう次の行へ進めるのがポイントで、join はあくまで「結果が要るときに待つ」ための呼び出しです。まずはこの3手(起動→続行→join)の流れを体に入れてください。

Rust

2スレッドの返り値 — String を作って返す

スレッドの返り値は整数に限らず、クロージャの最後の式の値ならどんな型でも join で受け取れることを示す例です。スレッド内で組み立てた String が所有権ごと返ってくるので、コピーも共有も発生しません。実務でも「ワーカーが作った結果オブジェクトを join でもらう」のが基本の形です。

Rust

32本のスレッドで手分けする

同じ形の計算を範囲で2分割し、2本のスレッドに同時に走らせる並列化の最小形です。それぞれの join の返り値を足せば、1本で計算した場合と同じ答えになります。大きな集計やバッチ処理を分担させる発想の出発点です。

Rust

4JoinHandle を Vec で管理する

スレッドの本数が増えたら、JoinHandle を Vec にためて最後にまとめて join するのが定番の形です。join する順番はコード側で決まっているので、表示順は実行ごとに変わりません。素数数えのような CPU を使う処理は、こうして分担する効果が出やすい代表例です。

Rust

5複数ログの行数を並列集計(風)

ログファイルごとに1スレッドを立てて行数を数える、実務の並列集計を模した例です(ファイル読み込みは固定データを返す関数で代用しています)。重い読み込みや解析が複数あるとき、それぞれをスレッドに任せて join で回収する、この形がそのまま使えます。

Rust