Initial commit
This commit is contained in:
37
solutions/20_threads/threads1.rs
Normal file
37
solutions/20_threads/threads1.rs
Normal file
@@ -0,0 +1,37 @@
|
||||
// This program spawns multiple threads that each runs for at least 250ms, and
|
||||
// each thread returns how much time it took to complete. The program should
|
||||
// wait until all the spawned threads have finished and should collect their
|
||||
// return values into a vector.
|
||||
|
||||
use std::{
|
||||
thread,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
fn main() {
|
||||
let mut handles = Vec::new();
|
||||
for i in 0..10 {
|
||||
let handle = thread::spawn(move || {
|
||||
let start = Instant::now();
|
||||
thread::sleep(Duration::from_millis(250));
|
||||
println!("Thread {i} done");
|
||||
start.elapsed().as_millis()
|
||||
});
|
||||
handles.push(handle);
|
||||
}
|
||||
|
||||
let mut results = Vec::new();
|
||||
for handle in handles {
|
||||
// Collect the results of all threads into the `results` vector.
|
||||
results.push(handle.join().unwrap());
|
||||
}
|
||||
|
||||
if results.len() != 10 {
|
||||
panic!("Oh no! Some thread isn't done yet!");
|
||||
}
|
||||
|
||||
println!();
|
||||
for (i, result) in results.into_iter().enumerate() {
|
||||
println!("Thread {i} took {result}ms");
|
||||
}
|
||||
}
|
||||
41
solutions/20_threads/threads2.rs
Normal file
41
solutions/20_threads/threads2.rs
Normal file
@@ -0,0 +1,41 @@
|
||||
// Building on the last exercise, we want all of the threads to complete their
|
||||
// work. But this time, the spawned threads need to be in charge of updating a
|
||||
// shared value: `JobStatus.jobs_done`
|
||||
|
||||
use std::{
|
||||
sync::{Arc, Mutex},
|
||||
thread,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
struct JobStatus {
|
||||
jobs_done: u32,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// `Arc` isn't enough if you want a **mutable** shared state.
|
||||
// We need to wrap the value with a `Mutex`.
|
||||
let status = Arc::new(Mutex::new(JobStatus { jobs_done: 0 }));
|
||||
// ^^^^^^^^^^^ ^
|
||||
|
||||
let mut handles = Vec::new();
|
||||
for _ in 0..10 {
|
||||
let status_shared = Arc::clone(&status);
|
||||
let handle = thread::spawn(move || {
|
||||
thread::sleep(Duration::from_millis(250));
|
||||
|
||||
// Lock before you update a shared value.
|
||||
status_shared.lock().unwrap().jobs_done += 1;
|
||||
// ^^^^^^^^^^^^^^^^
|
||||
});
|
||||
handles.push(handle);
|
||||
}
|
||||
|
||||
// Waiting for all jobs to complete.
|
||||
for handle in handles {
|
||||
handle.join().unwrap();
|
||||
}
|
||||
|
||||
println!("Jobs done: {}", status.lock().unwrap().jobs_done);
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
}
|
||||
62
solutions/20_threads/threads3.rs
Normal file
62
solutions/20_threads/threads3.rs
Normal file
@@ -0,0 +1,62 @@
|
||||
use std::{sync::mpsc, thread, time::Duration};
|
||||
|
||||
struct Queue {
|
||||
first_half: Vec<u32>,
|
||||
second_half: Vec<u32>,
|
||||
}
|
||||
|
||||
impl Queue {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
first_half: vec![1, 2, 3, 4, 5],
|
||||
second_half: vec![6, 7, 8, 9, 10],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn send_tx(q: Queue, tx: mpsc::Sender<u32>) {
|
||||
// Clone the sender `tx` first.
|
||||
let tx_clone = tx.clone();
|
||||
thread::spawn(move || {
|
||||
for val in q.first_half {
|
||||
println!("Sending {val:?}");
|
||||
// Then use the clone in the first thread. This means that
|
||||
// `tx_clone` is moved to the first thread and `tx` to the second.
|
||||
tx_clone.send(val).unwrap();
|
||||
thread::sleep(Duration::from_millis(250));
|
||||
}
|
||||
});
|
||||
|
||||
thread::spawn(move || {
|
||||
for val in q.second_half {
|
||||
println!("Sending {val:?}");
|
||||
tx.send(val).unwrap();
|
||||
thread::sleep(Duration::from_millis(250));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// You can optionally experiment here.
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn threads3() {
|
||||
let (tx, rx) = mpsc::channel();
|
||||
let queue = Queue::new();
|
||||
|
||||
send_tx(queue, tx);
|
||||
|
||||
let mut received = Vec::with_capacity(10);
|
||||
for value in rx {
|
||||
received.push(value);
|
||||
}
|
||||
|
||||
received.sort();
|
||||
assert_eq!(received, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user