Caution
お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。
std::thread::spawn() / join()
『std::thread::spawn()』で新しいスレッドを生成し、戻り値の『JoinHandle』の『join()』を呼ぶことでスレッドの終了を待機します。Rustはコンパイル時にデータ競合を防ぐスレッドセーフな設計になっています。
構文
use std::thread;
// スレッドを生成します。
let handle = thread::spawn(|| {
// スレッド内の処理
});
// スレッドの終了を待ちます。
handle.join().unwrap();
// moveクロージャで外部の変数をスレッドに渡します。
let data = 値;
let handle = thread::spawn(move || {
// dataはmoveされてスレッドが所有します。
println!("{:?}", data);
});
handle.join().unwrap();
メソッド一覧
| メソッド・関数 | 概要 |
|---|---|
| thread::spawn(f) | 新しいOSスレッドでクロージャfを実行します。JoinHandleを返します。 |
| handle.join() | スレッドの終了を待ちます。Result型を返します。 |
| thread::sleep(d) | 指定した時間だけスレッドをスリープさせます。 |
| thread::current() | 現在のスレッド情報(Thread型)を返します。 |
| thread::Builder::new() | スレッド名やスタックサイズを設定してからspawnできます。 |
サンプルコード
use std::thread;
use std::time::Duration;
fn main() {
// 複数スレッドを生成して結果を収集します。
let handles: Vec<_> = (0..5).map(|i| {
thread::spawn(move || {
// moveでiの所有権をスレッドに渡します。
thread::sleep(Duration::from_millis(10 * i));
format!("thread {} done", i)
})
}).collect();
// 各スレッドの戻り値を受け取ります。
for handle in handles {
let result = handle.join().unwrap();
println!("{}", result);
}
// 名前付きスレッドの生成
let builder = thread::Builder::new().name("worker".to_string());
let handle = builder.spawn(|| {
println!("thread name: {:?}", thread::current().name());
}).unwrap();
handle.join().unwrap();
}
概要
Rustのスレッドは、クロージャに渡すデータが『Send』トレイトを実装していることをコンパイル時に検証します。これによりデータ競合をコンパイル時に防ぐことができます。
スレッドに外部変数を渡す場合、参照ではなく所有権を渡す必要があるため、クロージャに『move』キーワードを付けて値をムーブさせるのが基本パターンです。
『join()』を呼ばずにメインスレッドが終了すると、生成したスレッドは強制終了されます。スレッドの処理が完了することを保証したい場合は必ず『join()』を呼んでください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。