チャネル

Rustは、スレッド間のコミュニケーションのために、非同期のチャネルを提供しています。チャネルは2つのエンドポイント、すなわち送信者と受信者を介して、情報の一方向への流れを作り出すことを可能にしています。

use std::sync::mpsc::{Sender, Receiver};
use std::sync::mpsc;
use std::thread;

static NTHREADS: i32 = 3;

fn main() {
    // チャネルには`Sender<T>`と`Receiver<T>`という2つのエンドポイントがあります。
    // ここで、`T`は送信されるメッセージの型です。
    // (型アノテーションは必須ではありません。)
    let (tx, rx): (Sender<i32>, Receiver<i32>) = mpsc::channel();
    let mut children = Vec::new();

    for id in 0..NTHREADS {
        // 送信者エンドポイントはコピーすることができます。
        let thread_tx = tx.clone();

        // ここでは、それぞれのスレッドが自身のIDを送信しています。
        let child = thread::spawn(move || {
            // スレッドは`thread_tx`の所有権をとり、それぞれのスレッドは
            // メッセージをチャネルにキューイングします。
            thread_tx.send(id).unwrap();

            // 送信はノンブロッキングなオペレーションなので、
            // メッセージを送信した後もすぐに実行を継続します。
            println!("thread {} finished", id);
        });

        children.push(child);
    }

    // ここで、全てのメッセージが収集されます。
    let mut ids = Vec::with_capacity(NTHREADS as usize);
    for _ in 0..NTHREADS {
        // `recv`メソッドはチャネルからメッセージを取り出します。
        // もし取り出せるメッセージが存在しない場合、`recv`は
        // 現在のスレッドをブロックします。
        ids.push(rx.recv());
    }
    
    // Wait for the threads to complete any remaining work
    for child in children {
        child.join().expect("oops! the child thread panicked");
    }

    // メッセージが送信された順番を表示。
    println!("{:?}", ids);
}