该程序的目的是让一个线程(主线程)从文件中读取I/O行,并将其输入到工作线程池中,后者的任务是对所提供的每一行执行一些处理。在本例中,处理正在运行String.contains()方法。
请注意,作为测试输入,我使用了一个巨大的英文字典单词.txt文件:
还要注意,您需要指定要扫描的文件的文件名,作为程序的唯一命令行参数。我主要关注线程模型和多线程实现,但也欢迎其他反馈;新的Rust程序员。
cargo.toml的spmc机箱ver为"0.2.2“。
extern crate spmc;
use spmc::channel;
use std::thread;
use std::io::BufReader;
use std::fs::File;
use std::io::BufRead;
use std::u32::MAX;
use std::env;
use std::sync::Arc;
fn main() -> Result<(), std::io::Error>
{
let args: Vec<String> = env::args().collect();
match args.len()
{
2 => {},
_ => return Err(std::io::Error::new(std::io::ErrorKind::Other, "Incorrect number of args"))
}
let filename = &args[1] as &str;
let f1 = File::open(filename)?;
let mut br = BufReader::new(f1);
let mut vecData: Vec<String> = Vec::new();
let (tx, rx) = spmc::channel();
let mut handles = Vec::new();
for n in 0..5 {
let rx = rx.clone();
handles.push(thread::spawn(move || {
loop
{
let mut line_to_check: Arc<String> = rx.recv().unwrap();
if line_to_check.contains("test")
{
println!("HIT: {}", line_to_check);
}
}
}));
}
let mut input_str = String::new();
let mut bytes_read: usize = 1;
while bytes_read != 0 {
let mut is_copy = input_str.clone();
bytes_read =
match br.read_line(&mut is_copy)
{
Ok(num) => num,
Err(err) => return Err(std::io::Error::new(std::io::ErrorKind::Other, "read_line failed...\n"))
};
let str_arc : Arc<String> = Arc::new(is_copy);
tx.send(str_arc);
}
Ok(())
}发布于 2018-11-07 19:03:42
在rustc下编译时,您的代码有许多警告。这些都是免费的代码评审提示,听他们!
对于所有错误,您都使用std::io::Error。这是可疑的,因为您的许多错误与I/O无关。就我个人而言,我喜欢使用来自Error机箱的failure。所有其他错误都可以由failure::Error操作符自动转换为?。
最后的代码块有以下几个问题:
let mut input_str = String::new();
let mut bytes_read: usize = 1;
while bytes_read != 0 {
let mut is_copy = input_str.clone();按照代码的工作方式,input_str从未被修改过。因此,您总是为循环的每一次迭代克隆一个空字符串。您应该在这里创建一个空字符串,并完全摆脱input_str。
bytes_read =
match br.read_line(&mut is_copy)
{
Ok(num) => num,
Err(err) => return Err(std::io::Error::new(std::io::ErrorKind::Other, "read_line failed...\n"))
};read_line函数的全部要点是,您可以在循环迭代之间重用在String中分配的内存。由于您不这样做,这是错误的界面。相反,使用for line in br.lines()在文件中的行上获得迭代器:
let str_arc : Arc<String> = Arc::new(is_copy);
tx.send(str_arc);这里没有理由使用Arc。如果发送和接收线程都要保持对字符串的引用,则只需要一个Arc。然而,这里的情况并非如此。在这里,您可以将String从一个线程发送到另一个线程,而不需要Arc。
总的来说,这是对线程的错误使用。你的程序将受到它从磁盘读取数据的速度的限制。因此,你不可能通过这样的多线程来提高速度。
https://codereview.stackexchange.com/questions/206142
复制相似问题