如何将向量发送到 Rust 中的生成线程

Kir*_*kov 2 multithreading thread-safety rust

[更新] 有错误的图像已替换为纯代码(根据评论)

我是 Rust 新手,来自 JS。所以我的线程有问题。

问题1

我想尝试加快我的程序速度,但我不明白如何发送我的批次来运行。

fn read_lines(reader: BufReader<File>) -> Vec<JoinHandle<()>> {
    let mut batch = vec![];
    let mut children_th = vec![];
    for line in reader.lines() {
        let line_str = line.expect("invalid line");
        if batch.len() >= BATCH_SIZE && !line_str.contains('[') {
            batch.push(line_str);
            children_th.push(thread::spawn(|| process_data(batch.clone())));
            batch.clear();
        }
    }
    children_th
}

fn process_data(lines: Vec<String>) {
    let mut rus_word = "".to_string();
    let mut definition: String = "".to_string();
    let mut parsed_result: Vec<VedyDictionary> = vec![];
    for line_str in lines {
        if line_str.trim().chars().count() > 1 {
            if !line_str.contains('[') {
                if !rus_word.is_empty() {
                    parsed_result.push(parse_to_dictionary(rus_word, &definition));
                    definition = "".to_string();
                }
                rus_word = line_str.trim().to_string();
            } else {
                definition.push_str(line_str.trim());
                definition.push('\n');
            }
        }
    }
    write_jsons(&parsed_result);
}

Run Code Online (Sandbox Code Playgroud)

在这种情况下我收到此错误:

error[E0382]: borrow of moved value: `batch`
  --> src/main.rs:41:12
   |
36 |     let mut batch = vec![];
   |         --------- move occurs because `batch` has type `Vec<std::string::String>`, which does not implement the `Copy` trait
...
41 |         if batch.len() >= BATCH_SIZE && !line_str.contains('[') {
   |            ^^^^^^^^^^^ value borrowed here after move
...
44 |             children_th.push(thread::spawn(move || process_data(batch.clone(), index)));
   |                                            ------- value moved into closure here, in previous iteration of loop
Run Code Online (Sandbox Code Playgroud)

我在这里找到了解决方法,但看起来很难看。我想我做错了。有人可以推荐一些东西吗?解决方法:

error[E0382]: borrow of moved value: `batch`
  --> src/main.rs:41:12
   |
36 |     let mut batch = vec![];
   |         --------- move occurs because `batch` has type `Vec<std::string::String>`, which does not implement the `Copy` trait
...
41 |         if batch.len() >= BATCH_SIZE && !line_str.contains('[') {
   |            ^^^^^^^^^^^ value borrowed here after move
...
44 |             children_th.push(thread::spawn(move || process_data(batch.clone(), index)));
   |                                            ------- value moved into closure here, in previous iteration of loop
Run Code Online (Sandbox Code Playgroud)

问题2

是否可以这样做:

fn read_lines(reader: BufReader<File>) -> Vec<JoinHandle<()>> {
    let mut batch = vec![];
    let mut children_th = vec![];
    for line in reader.lines() {
        let line_str = line.expect("invalid line");
        if batch.len() >= BATCH_SIZE && !line_str.contains('[') {
            batch.push(line_str);
            let batch_clone = batch.clone(); // clone here
            children_th.push(thread::spawn(move || process_data(batch_clone))); // move cloned variable here
            batch.clear();
        } else {
            batch.push(line_str);
        }
    }
    children_th
}
Run Code Online (Sandbox Code Playgroud)

谢谢!

cdh*_*wie 7

Vec我注意到您在生成新线程后立即清除了本地副本。换句话说,您希望将 的内容提供Vec给新线程并以空的 重新开始Vec

当您在 Rust 中移动变量中的值时,该变量实际上再次变为未初始化,这意味着即使在移动它之后您也可以为其分配新值。因此,您根本不需要克隆。将本地移动Vec到新的线程闭包中,并Vec在执行此操作后分配一个新的:

batch.push(line_str);
children_th.push(thread::spawn(move || process_data(batch)));
// The batch variable is now "dead" but we can revive it by assigning
// a new value to it:
batch = vec![];
Run Code Online (Sandbox Code Playgroud)

Vec这避免了不必要的整个内容的克隆。