此问题已经在这里有了答案:
此程序随机打印索引编号,例如1、4、2、3、100...。
use std::thread;
fn main() {
for x in 0..100 {
print!("{}: {:?} ", x, child.join());
}
}
但是,一旦我添加了ping()
函数,该函数除了执行控制台输出外,将不再并发执行,而是仅迭代ping()
函数。
extern crate serde;
extern crate serde_derive;
extern crate reqwest;
use reqwest::Client;
use std::thread;
use std::process::Command;
fn main() {
for x in 0..100 {
let child = thread::spawn(move || {
ping(x);
});
print!("{}: {:?} ", x, child.join());
}
}
fn ping(x: i32) {
let output = if cfg!(target_os = "windows") {
Command::new("cmd")
.args(&["/C", "echo hello"])
.output()
.expect("failed to execute process")
} else {
Command::new("sh")
.arg("-c")
.arg("https://keisugano.blogspot.com/")
.output()
.expect("failed to execute process")
};
println!("{:?}", output);
}
此问题的根本原因是什么,我该如何解决?
第一个示例是不完整的,没有实际产生线程,所以不确定那里发生了什么。
这里的关键点是join
正在阻塞,这意味着在基础线程完成之前它不会返回。从the documentation:
pub fn join(self) -> Result<T>
等待关联线程完成。
就原子内存顺序而言,相关线程的完成与此函数的返回同步。换句话说,该线程执行的所有操作在连接返回之后发生的所有操作之前被排序。
有了这些新知识,很明显您的代码实际上是在做:创建一个新线程,等待它完成,然后创建下一个线程。因此它仍然是顺序的,显然不是您想要的。
解决方案很简单:首先创建所有线程,然后等待它们完成,如下所示:
use std::thread;
fn main() {
let handles = (0..100)
.into_iter()
.map(|x| {
thread::spawn(move || {
ping(x);
})
})
.collect::<Vec<_>>();
for thread in handles {
thread.join().unwrap();
}
}
fn ping(x: i32) {
// Do things.
}