DEV Community

BC
BC

Posted on

Day19:Communicating via MPSC channel - 100DayOfRust

Example 1

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

fn main() {
    let (sender, recver) = mpsc::channel();
    thread::spawn(move || {
        sender.send("hello world").unwrap();
    });
    let s = recver.recv().unwrap();
    println!("Received: {}", s); 
}
Enter fullscreen mode Exit fullscreen mode

Result:

Received: hello world
Enter fullscreen mode Exit fullscreen mode

Example 2

use std::thread;
use std::time;
use std::sync::mpsc;

fn main() {
    let (sender, recver) = mpsc::channel();

    thread::spawn(move || {
        let list = vec![
            "hello".to_owned(),
            "world".to_owned(),
            "and".to_owned(),
            "rust".to_owned(),
        ];
        for s in list {
            sender.send(s).unwrap();
            thread::sleep(time::Duration::from_secs(1));
        }
    }); 
    for s in recver {
        println!("Received: {}", s); 
    }   
}
Enter fullscreen mode Exit fullscreen mode

Result:

Received: hello
Received: world
Received: and
Received: rust
Enter fullscreen mode Exit fullscreen mode

Example 3

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

fn main() {
    let (tx, rx) = mpsc::channel();
    let job_count = 10; 

    for i in 0..job_count {
        let tx = tx.clone();
        thread::spawn(move || {
            tx.send(i).unwrap();
        });
    }   

    for _i in 0..job_count {
        println!("Recv: {}", rx.recv().unwrap());
    }
}
Enter fullscreen mode Exit fullscreen mode

Result: (b/c the result returned in thread, your print might be different)

Recv: 0
Recv: 1
Recv: 3
Recv: 2
Recv: 5
Recv: 4
Recv: 6
Recv: 7
Recv: 8
Recv: 9
Enter fullscreen mode Exit fullscreen mode

In this example, we have 11 sender side (tx in the code) open, the original tx and cloned 10 tx. The opened tx in thread will be closed once the thread finished running. This means after running 10 threads, we still have 1 tx open. For rx we call recv 10 times then close.

We could also treat rx as iterator, use for .. in to receive the passed number:

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

fn main() {
    let (tx, rx) = mpsc::channel();
    let job_count = 10; 

    for i in 0..job_count {
        let tx = tx.clone();
        thread::spawn(move || {
            tx.send(i).unwrap();
        });
    }   

    for num in rx {
        println!("Recv: {}", num);
    }   
}
Enter fullscreen mode Exit fullscreen mode

If we run this, we will get something like:

Recv: 1
Recv: 2
Recv: 3
Recv: 4
Recv: 0
Recv: 6
Recv: 5
Recv: 7
Recv: 8
Recv: 9

Enter fullscreen mode Exit fullscreen mode

But then our program is blocked, it keeps waiting for message in rx, the program won't quit. The problem is, when we use for .. in, system will keep trying to get message from channel until all sender ends close. Like we mentioned above, we have opened 11 sender ends, and thread closed 10, there is still one left open - the original one. So we need to close the original one:

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

fn main() {
    let (tx, rx) = mpsc::channel();
    let job_count = 10; 

    for i in 0..job_count {
        let tx = tx.clone();
        thread::spawn(move || {
            tx.send(i).unwrap();
        });
    }
    // we close the original sender end   
    drop(tx);

    for num in rx {
        println!("Recv: {}", num);
    }   
}
Enter fullscreen mode Exit fullscreen mode

Now our program can run and exit successfully after receiving all message from the channel.

Recv: 0
Recv: 1
Recv: 2
Recv: 4
Recv: 5
Recv: 3
Recv: 7
Recv: 6
Recv: 9
Recv: 8
Enter fullscreen mode Exit fullscreen mode

Top comments (0)