让 Rust 线程摆脱阻塞操作的标准方法是什么?
What is the standard way to get a Rust thread out of blocking operations?
来自Java,习惯了
的成语
while (true) {
try {
someBlockingOperation();
} catch (InterruptedException e) {
Thread.currentThread.interrupt(); // re-set the interrupted flag
cleanup(); // whatever is necessary
break;
}
}
据我所知,这适用于整个 JDK 任何可能阻塞的事情,例如从文件、套接字、队列甚至 Thread.sleep()
.
阅读 Rust 中如何完成此操作,我发现提到了许多看似特殊的解决方案,例如 mio
、tokio
。我还找到 ErrorKind::Interrupted
并尝试通过向线程发送 SIGINT
来获得此 ErrorKind
,但线程似乎立即死亡而没有留下任何(返回)痕迹。
这是我使用的代码(注意:还不是很精通 Rust,所以它可能看起来有点奇怪,但它运行):
use std::io;
use std::io::Read;
use std::thread;
pub fn main() {
let sub_thread = thread::spawn(|| {
let mut buffer = [0; 10];
loop {
let d = io::stdin().read(&mut buffer);
println!("{:?}", d);
let n = d.unwrap();
if n == 0 {
break;
}
println!("-> {:?}", &buffer[0..n]);
}
});
sub_thread.join().unwrap();
}
"blocking operations",我的意思是:
- 睡觉
- 套接字IO
- 文件输入
- 队列 IO(还不确定队列在 Rust 中的位置)
向线程发出信号的相应方法是什么,例如 Java 中的 Thread.interrupt()
,是时候打包回家了?
没有这样的事情。堵就是堵。
相反,您故意使用 非阻塞 的工具。这就是 mio、Tokio 或 futures 等库的用武之地——它们处理将所有这些非阻塞、异步的部分粘在一起的架构。
catch (InterruptedException e)
Rust 没有例外。如果您希望处理失败案例,最好用 Result
.
表示
Thread.interrupt()
除了在线程中设置一个标志,一些代码可能会检查然后抛出异常之外,这实际上并没有做任何事情。您可以自己构建相同的结构。一个简单的实现:
use std::{
sync::{
atomic::{AtomicBool, Ordering},
Arc,
},
thread,
time::Duration,
};
fn main() {
let please_stop = Arc::new(AtomicBool::new(false));
let t = thread::spawn({
let should_i_stop = please_stop.clone();
move || {
while !should_i_stop.load(Ordering::SeqCst) {
thread::sleep(Duration::from_millis(100));
println!("Sleeping");
}
}
});
thread::sleep(Duration::from_secs(1));
please_stop.store(true, Ordering::SeqCst);
t.join().unwrap();
}
睡觉
据我所知,无法打扰。文档甚至说:
On Unix platforms this function will not return early due to a signal
套接字输入
您使用 set_nonblocking
and then handle ErrorKind::WouldBlock
.
等方法将套接字置于非阻塞模式
另请参阅:
文件输入
执行异步文件 IO 并没有真正好的跨平台方式。大多数实现启动一个线程池并在那里执行阻塞操作,通过非阻塞的方式发送数据。
另请参阅:
队列 IO
也许你的意思是 MPSC channel, in which case you'd use tools like try_recv
。
另请参阅:
- How to terminate or suspend a Rust thread from another thread?
- What does java.lang.Thread.interrupt() do?
来自Java,习惯了
的成语while (true) {
try {
someBlockingOperation();
} catch (InterruptedException e) {
Thread.currentThread.interrupt(); // re-set the interrupted flag
cleanup(); // whatever is necessary
break;
}
}
据我所知,这适用于整个 JDK 任何可能阻塞的事情,例如从文件、套接字、队列甚至 Thread.sleep()
.
阅读 Rust 中如何完成此操作,我发现提到了许多看似特殊的解决方案,例如 mio
、tokio
。我还找到 ErrorKind::Interrupted
并尝试通过向线程发送 SIGINT
来获得此 ErrorKind
,但线程似乎立即死亡而没有留下任何(返回)痕迹。
这是我使用的代码(注意:还不是很精通 Rust,所以它可能看起来有点奇怪,但它运行):
use std::io;
use std::io::Read;
use std::thread;
pub fn main() {
let sub_thread = thread::spawn(|| {
let mut buffer = [0; 10];
loop {
let d = io::stdin().read(&mut buffer);
println!("{:?}", d);
let n = d.unwrap();
if n == 0 {
break;
}
println!("-> {:?}", &buffer[0..n]);
}
});
sub_thread.join().unwrap();
}
"blocking operations",我的意思是:
- 睡觉
- 套接字IO
- 文件输入
- 队列 IO(还不确定队列在 Rust 中的位置)
向线程发出信号的相应方法是什么,例如 Java 中的 Thread.interrupt()
,是时候打包回家了?
没有这样的事情。堵就是堵。
相反,您故意使用 非阻塞 的工具。这就是 mio、Tokio 或 futures 等库的用武之地——它们处理将所有这些非阻塞、异步的部分粘在一起的架构。
catch (InterruptedException e)
Rust 没有例外。如果您希望处理失败案例,最好用 Result
.
Thread.interrupt()
除了在线程中设置一个标志,一些代码可能会检查然后抛出异常之外,这实际上并没有做任何事情。您可以自己构建相同的结构。一个简单的实现:
use std::{
sync::{
atomic::{AtomicBool, Ordering},
Arc,
},
thread,
time::Duration,
};
fn main() {
let please_stop = Arc::new(AtomicBool::new(false));
let t = thread::spawn({
let should_i_stop = please_stop.clone();
move || {
while !should_i_stop.load(Ordering::SeqCst) {
thread::sleep(Duration::from_millis(100));
println!("Sleeping");
}
}
});
thread::sleep(Duration::from_secs(1));
please_stop.store(true, Ordering::SeqCst);
t.join().unwrap();
}
睡觉
据我所知,无法打扰。文档甚至说:
On Unix platforms this function will not return early due to a signal
套接字输入
您使用 set_nonblocking
and then handle ErrorKind::WouldBlock
.
另请参阅:
文件输入
执行异步文件 IO 并没有真正好的跨平台方式。大多数实现启动一个线程池并在那里执行阻塞操作,通过非阻塞的方式发送数据。
另请参阅:
队列 IO
也许你的意思是 MPSC channel, in which case you'd use tools like try_recv
。
另请参阅:
- How to terminate or suspend a Rust thread from another thread?
- What does java.lang.Thread.interrupt() do?