スレッド

Module std::thread::spawnを使うことで新しいスレッドを作ることができます。::spanには関数を渡しその関数の戻り値TをラップしたJoinHandle<T>を返します。

以下は例です。スレッドはJoinHandle::joinを使わなければスレッドの完了を待ってくれないのでhello from a threadと表示されずに終了してしまいます。

use std::thread;

let handler = thread::spawn(|| {
  println!("hello from a thread");
  // `::join`で待ってるのでちゃんとターミナルなどに表示される
});

let thirty_three = handler.join().unwrap();

関数の戻り値はjoin().unwrap()で受け取れます。

use std::thread;

let handler = thread::spawn(|| {
  33
});

let thirty_three = handler.join().unwrap();

assert_eq!(thirty_three, 33);

Function std::sync::mpsc::channel を使った方法でも値の送受信ができます。

上記の方法のようにJooinHandle::joinだけでなく以下のreceiiver.recvを使う方法でもスレッド処理を待つことができます。

use std::sync::mpsc::channel;
use std::thread;

let (sender, receiver) = channel();

thread::spawn(move || {
  sender.send(33).unwrap();
});

println!("{}", receiver.recv().unwrap())

送信した値は、FIFO で受信できます。また、注意として送信する値はSendを持ってる必要があります。

以下は、

  • i=0の時は2秒待つ
  • i=1の時は1秒待つ
  • i=2の時は待たない

で合計3回送信する例です。

スレッドでメインスレッドよりもVecの各u64が長生きしてしまう可能性や、senderは所有権を渡す必要からいくらか::cloneしてます。

これは1秒毎に210と表示されプログラムが終了します。

use std::sync::mpsc::channel;
use std::sync::Arc;
use std::thread;
use std::time::Duration;

let (sender, receiver) = channel();

let secs = vec![Arc::new(2_u64), Arc::new(1_u64), Arc::new(0_u64)];

{
  for (i, sec) in secs.iter().enumerate() {
    let sender = sender.clone();
    let sec = sec.clone();

    thread::spawn(move || {
      thread::sleep(Duration::from_secs(*sec));
      sender.send(i).unwrap();
    });
  }

  for _ in 0..secs.len() {
    println!("{:?}", receiver.recv().unwrap());
  }
}

受信でもfor構文を使っているのは、FIFO なので受信側も送信側と同じ回数繰り返し実行しなければすべて取り出せないからです。例えばこの部分を、

// for _ in 0..secs.len() {
  println!("{:?}", receiver.recv().unwrap());
// }

だけにすると、2だけが表示されプログラムが終了します。