Rust多线程代码报错:FromIterator<()>未实现于Vec<JoinHandle>,求排查
Rust线程代码编译错误排查
你的代码目标是启动多个线程,先输出所有线程启动信息,再输出线程结束信息,但编译时出现错误:
the trait FromIterator<()> is not implemented for Vec<JoinHandle<>> the trait FromIterator<T> is implemented for Vec<T>
问题根源
错误出在map闭包的返回值上:闭包最后一行的builder.spawn(...).unwrap();末尾加了分号,这会让闭包返回单元类型(),而不是你需要的JoinHandle<String>。collect()方法需要迭代器返回的类型和Vec的泛型类型一致(这里是JoinHandle<String>),但现在迭代器输出的是(),自然无法匹配Vec<JoinHandle<String>>的类型要求,从而触发这个 trait 未实现的错误。
修复后的代码
只需要去掉map闭包最后一行的分号,让闭包返回spawn调用后得到的JoinHandle<String>即可:
use std::thread::{self, JoinHandle}; use std::time::Duration; use rand::Rng; fn main() { let handles: Vec<JoinHandle<String>> = (0..=10).map(|i| { let delay = rand::thread_rng().gen_range(10..=2000); let builder = thread::Builder::new().name(format!("Thread-{}", i)); // 去掉末尾的分号,让闭包返回JoinHandle<String> builder.spawn(move || { println!( "thread started = {}", thread::current().name().unwrap() ); thread::sleep(Duration::from_millis(delay)); thread::current().name().unwrap().to_owned() }).unwrap() }).collect(); for h in handles { let r = h.join().unwrap(); println!("thread done = {:?}", r); } }
额外说明
不过要注意:即使修复了编译错误,线程的启动信息也可能和结束信息交替输出——因为线程是并行执行的,主线程在收集完所有JoinHandle后才会开始等待线程结束,但子线程启动后会立即打印启动信息,而主线程收集JoinHandle的过程本身需要时间,所以子线程可能在主线程完成收集前就启动并打印内容。如果要严格实现先输出所有线程启动信息,再输出结束信息,需要额外的同步机制(比如Barrier),让所有子线程先完成启动信息的打印,再进入休眠,主线程等待所有子线程完成启动后再等待它们结束。
内容的提问来源于stack exchange,提问作者Ganesh11
相关产品推荐
相关产品推荐

