Android程序员初学Rust-线程

Rust 中的线程与其他语言中的线程工作方式类似。

Rust 复制代码
use std::thread;
use std::time::Duration;

fn main() {
    thread::spawn(|| {
        for i in 0..10 {
            println!("Count in thread: {i}!");
            thread::sleep(Duration::from_millis(5));
        }
    });

    for i in 0..5 {
        println!("Main thread: {i}");
        thread::sleep(Duration::from_millis(5));
    }
}

输出如下:

Rust 复制代码
// Output
Main thread: 0  
Count in thread: 0!  
Main thread: 1  
Count in thread: 1!  
Main thread: 2  
Count in thread: 2!  
Main thread: 3  
Count in thread: 3!  
Main thread: 4  
Count in thread: 4!

生成新线程不会在 main 函数末尾阻塞直到程序终止。

线程 panic 彼此独立,在新线程中触发一个 panic,不会使主线程 panic

上述代码主线程结束了程序,而生成线程并不会使程序继续运行,所以计数到 4 程序就终止了。

我们如何等待生成的线程完成呢?

thread::spawn 会返回一个 JoinHandle

JoinHandle 有一个 .join() 方法,该方法会阻塞线程。

使用 let handle = thread::spawn(...),然后在后面调用 handle.join() 来等待线程完成,以使程序能完整地数到 9

Rust 复制代码
fn main() {
   let handle = thread::spawn(|| {
        for i in 0..10 {
            println!("Count in thread: {i}!");
            thread::sleep(Duration::from_millis(5));
        }
    });

    for i in 0..5 {
        println!("Main thread: {i}");
        thread::sleep(Duration::from_millis(5));
    }
    
    handle.join();
}

如果我们想返回一个值呢?

thread::spawn 的闭包返回 TJoinHandle.join() 方法返回 thread::Result<T> 使用 handle.join()Result 返回值来获取返回的值:

Rust 复制代码
fn main() {
   let handle = thread::spawn(|| {
        1 + 3
    });
    
    println!("{}",handle.join().unwrap());
}

// Output
// 4

好的,现在我们可以从线程中返回值了!那接收输入该怎么做呢?

Rust 复制代码
fn main() {
    let adder = 4;

    let handle = thread::spawn(|| { // compile error: may outlive borrowed value `adder`
        1 + adder
    });

    println!("{}", handle.join().unwrap());
}

我们尝试通过借用的方式,将 adder 借用到线程中使用,这段代码并不能通过编译。原因很简单,线程可能活的比 adder 更长,所以,这里需要转移所有权:

Rust 复制代码
fn main() {
    let adder = 4;

    let handle = thread::spawn(move || {
        1 + adder
    });

    println!("{}", handle.join().unwrap());
}

// Output
// 5

如果你还是想借用,作用域线程可能正是你想要的:

Rust 复制代码
fn main() {
    let adder = 4;

    thread::scope(|scope| {
        let handle =  scope.spawn(|| {
            1 + adder
        });
        
        println!("{}", handle.join().unwrap());
    });
}

thread::scope 函数执行完成时,所有 scope.spawn 生成的线程都必定已经完成,所以这些线程能够借用数据。

正常的 Rust 借用规则在此同样适用:你要么让一个线程可变地借用数据,要么让任意数量的线程不可变地借用数据。

相关推荐
专注VB编程开发20年6 小时前
CSS 的命名方式像是 PowerShell 的动词-名词结构,缺乏面向对象的层级关系
开发语言·后端·rust
伍哥的传说7 小时前
Tailwind CSS v4 终极指南:体验 Rust 驱动的闪电般性能与现代化 CSS 工作流
前端·css·rust·tailwindcss·tailwind css v4·lightning css·utility-first
专注VB编程开发20年10 小时前
rust语言-对象多级访问
服务器·前端·rust
编码浪子13 小时前
趣味学RUST基础篇(构建一个命令行程序2重构)
开发语言·重构·rust
susnm14 小时前
组件生命周期
rust·全栈
bruce5411015 小时前
Axum 最佳实践:如何构建优雅的 Rust 错误处理系统?(三)
rust
Source.Liu1 天前
【Python基础】 15 Rust 与 Python 基本类型对比笔记
笔记·python·rust
咸甜适中2 天前
rust语言 (1.88) egui (0.32.1) 学习笔记(逐行注释)(二十六)windows平台运行时隐藏控制台
笔记·学习·rust·egui
编码浪子2 天前
趣味学RUST基础篇(构建命令行程序1)
开发语言·后端·rust
周小码2 天前
极快文本嵌入推理:Rust构建高性能嵌入推理解决方案
开发语言·后端·rust