Introduction
In Rust, Receiver
is a type used to receive messages from a channel. It is part of the standard library's std::sync::mpsc
module, where mpsc
stands for "multiple producer, single consumer." Channels provide a way for different parts of your code to communicate with each other, especially in concurrent programming. The Receiver
is used to read messages sent by the corresponding Sender
.
Using Receiver
To use Receiver
, you need to create a channel using the std::sync::mpsc::channel
function, which returns a (Sender, Receiver)
pair. You can then use the Receiver
to receive messages sent through the channel.
use std::sync::mpsc;
use std::thread;
use std::time::Duration;
fn main() {
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
tx.send("Hello from the spawned thread!").unwrap();
});
let received = rx.recv().unwrap();
println!("Received: {}", received);
}
// Output:
// Received: Hello from the spawned thread!
Key Methods
Below are some of the key methods exposed by the Receiver
class:
recv
Blocks the current thread until a message is available and returns it. If the channel is closed, it returns an Err
.
use std::sync::mpsc;
use std::thread;
fn main() {
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
tx.send(42).unwrap();
});
let received = rx.recv().unwrap();
println!("Received: {}", received);
}
// Output:
// Received: 42
try_recv
Tries to receive a message from the channel without blocking. It returns immediately with a Result
, which is Ok(T)
if a message is available, or Err(TryRecvError)
if the channel is empty or closed.
use std::sync::mpsc;
use std::thread;
use std::time::Duration;
fn main() {
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
tx.send(42).unwrap();
});
thread::sleep(Duration::from_millis(100));
match rx.try_recv() {
Ok(received) => println!("Received: {}", received),
Err(e) => println!("Failed to receive: {:?}", e),
}
}
// Output:
// Received: 42
iter
Returns an iterator that will yield messages received from the channel. The iterator ends when the channel is closed and all messages have been received.
use std::sync::mpsc;
use std::thread;
fn main() {
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
for i in 0..5 {
tx.send(i).unwrap();
}
});
for received in rx.iter() {
println!("Received: {}", received);
}
}
// Output:
// Received: 0
// Received: 1
// Received: 2
// Received: 3
// Received: 4
Example Usage
Example 1: Basic Usage
use std::sync::mpsc;
use std::thread;
fn main() {
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
tx.send("Hello from the spawned thread!").unwrap();
});
let received = rx.recv().unwrap();
println!("Received: {}", received);
}
// Output:
// Received: Hello from the spawned thread!
Example 2: Receiving Multiple Messages
use std::sync::mpsc;
use std::thread;
fn main() {
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
tx.send(1).unwrap();
tx.send(2).unwrap();
tx.send(3).unwrap();
});
for _ in 0..3 {
let received = rx.recv().unwrap();
println!("Received: {}", received);
}
}
// Output:
// Received: 1
// Received: 2
// Received: 3
Example 3: Non-blocking Receive
use std::sync::mpsc;
use std::thread;
use std::time::Duration;
fn main() {
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
thread::sleep(Duration::from_millis(50));
tx.send(42).unwrap();
});
match rx.try_recv() {
Ok(received) => println!("Received: {}", received),
Err(e) => println!("Failed to receive: {:?}", e),
}
thread::sleep(Duration::from_millis(100));
match rx.try_recv() {
Ok(received) => println!("Received: {}", received),
Err(e) => println!("Failed to receive: {:?}", e),
}
}
// Output:
// Failed to receive: Empty
// Received: 42
Example 4: Iterating Over Messages
use std::sync::mpsc;
use std::thread;
fn main() {
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
for i in 0..5 {
tx.send(i).unwrap();
}
});
for received in rx.iter() {
println!("Received: {}", received);
}
}
// Output:
// Received: 0
// Received: 1
// Received: 2
// Received: 3
// Received: 4
Example 5: Handling Channel Closure
use std::sync::mpsc;
use std::thread;
fn main() {
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
tx.send(1).unwrap();
// Dropping the sender to close the channel
drop(tx);
});
loop {
match rx.recv() {
Ok(received) => println!("Received: {}", received),
Err(_) => {
println!("Channel closed");
break;
}
}
}
}
// Output:
// Received: 1
// Channel closed
Considerations
- Channels provide a powerful way to communicate between threads, but they can introduce complexity and potential for deadlocks if not managed carefully.
- Always handle the
Result
returned byrecv
andtry_recv
to manage possible errors when the channel is closed. - Dropping the
Sender
will close the channel, causingrecv
to return an error once all messages have been received.
See Also
- Sender - The sending half of a channel used to send messages.
- JoinHandle - A handle for managing the lifecycle of a thread.
- Mutex - A mutual exclusion primitive for protecting shared data.