首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >锈蚀任务队列

锈蚀任务队列
EN

Code Review用户
提问于 2018-10-23 23:29:12
回答 1查看 881关注 0票数 3

该程序的目的是让一个线程(主线程)从文件中读取I/O行,并将其输入到工作线程池中,后者的任务是对所提供的每一行执行一些处理。在本例中,处理正在运行String.contains()方法。

请注意,作为测试输入,我使用了一个巨大的英文字典单词.txt文件:

还要注意,您需要指定要扫描的文件的文件名,作为程序的唯一命令行参数。我主要关注线程模型和多线程实现,但也欢迎其他反馈;新的Rust程序员。

cargo.toml的spmc机箱ver为"0.2.2“。

代码语言:javascript
复制
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(())
}
EN

回答 1

Code Review用户

发布于 2018-11-07 19:03:42

在rustc下编译时,您的代码有许多警告。这些都是免费的代码评审提示,听他们!

对于所有错误,您都使用std::io::Error。这是可疑的,因为您的许多错误与I/O无关。就我个人而言,我喜欢使用来自Error机箱的failure。所有其他错误都可以由failure::Error操作符自动转换为?

最后的代码块有以下几个问题:

代码语言:javascript
复制
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

代码语言:javascript
复制
    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()在文件中的行上获得迭代器:

代码语言:javascript
复制
    let str_arc : Arc<String> = Arc::new(is_copy);
    tx.send(str_arc);

这里没有理由使用Arc。如果发送和接收线程都要保持对字符串的引用,则只需要一个Arc。然而,这里的情况并非如此。在这里,您可以将String从一个线程发送到另一个线程,而不需要Arc

总的来说,这是对线程的错误使用。你的程序将受到它从磁盘读取数据的速度的限制。因此,你不可能通过这样的多线程来提高速度。

票数 4
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/206142

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档