如何在Rust中发送vector到派生线程


[UPDATE]带有错误的图像被替换为纯代码(根据注释)

我是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);
}

在这种情况下我得到这个错误:

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

我在这里找到了一个解决方案,但它看起来很丑。我想我做错了。有人能推荐点什么吗?解决方法:

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
}

问题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);
children_th.push(thread::spawn(process_data(batch.clone()))); // no || clouser
batch.clear();
}
}
children_th
}

谢谢!

我注意到您在生成新线程后立即清除了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![];

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

最新更新