对于终止和挂起线程,可以使用通道.
Terminated externally
在worker循环的每次迭代中,我们判断是否有人通过渠道通知我们.如果是,或者通道的另一端超出了范围,我们就打破循环.
use std::io::{self, BufRead};
use std::sync::mpsc::{self, TryRecvError};
use std::thread;
use std::time::Duration;
fn main() {
println!("Press enter to terminate the child thread");
let (tx, rx) = mpsc::channel();
thread::spawn(move || loop {
println!("Working...");
thread::sleep(Duration::from_millis(500));
match rx.try_recv() {
Ok(_) | Err(TryRecvError::Disconnected) => {
println!("Terminating.");
break;
}
Err(TryRecvError::Empty) => {}
}
});
let mut line = String::new();
let stdin = io::stdin();
let _ = stdin.lock().read_line(&mut line);
let _ = tx.send(());
}
Suspending and resuming
我们使用recv()
,它会暂停线程,直到有东西到达通道.为了恢复线程,需要通过通道发送一些内容;在这种情况下,单位值为()
.如果信道的传输端被丢弃,recv()
将返回Err(())
——我们使用它退出环路.
use std::io::{self, BufRead};
use std::sync::mpsc;
use std::thread;
use std::time::Duration;
fn main() {
println!("Press enter to wake up the child thread");
let (tx, rx) = mpsc::channel();
thread::spawn(move || loop {
println!("Suspending...");
match rx.recv() {
Ok(_) => {
println!("Working...");
thread::sleep(Duration::from_millis(500));
}
Err(_) => {
println!("Terminating.");
break;
}
}
});
let mut line = String::new();
let stdin = io::stdin();
for _ in 0..4 {
let _ = stdin.lock().read_line(&mut line);
let _ = tx.send(());
}
}
Other tools
渠道是完成这些任务最简单、最自然(IMO)的方式,但不是最有效的方式.在std::sync
模块中还可以找到其他并发原语.它们可能比某个特定级别的任务更高效.