std::thread

创建线程

  • thread::spawn() - 创建普通线程
  • thread::scope() - 创建作用域线程(内部使用 s.spawn())
  • Builder::spawn() - 使用构建器创建普通线程
  • Builder::spawn_scoped() - 使用构建器创建作用域线程(在thread::scope()内部使用)

thread::spawn创建

thread::spawn(|| {
    todo!();
})

使用

use std::thread;
use std::time::Duration;

fn main() {
    let _ = thread::spawn(|| {
        for i in 1..10 {
            println!("thread::spawn: {}", i);
            thread::sleep(Duration::from_millis(1));
        }
    });

    for i in 1..5 {
        println!("main: {}", i);
        thread::sleep(Duration::from_millis(1));
    }
}
main: 1
thread::spawn: 1
main: 2
thread::spawn: 2
main: 3
thread::spawn: 3
main: 4
thread::spawn: 4

handle

join

thread::spawn返回一个JoinHandle,这个JoinHandle可以等待线程结束。
handle.join().unwrap();让当前线程等待handle的线程结束,并且获取线程返回值。

等待线程
use std::thread;
use std::time::Duration;

fn main() {
    let handle = thread::spawn(|| {
        for i in 1..5 {
            println!("thread::spawn: {}", i);
            thread::sleep(Duration::from_millis(1));
        }
    });

    for i in 1..3 {
        println!("main: {}", i);
        thread::sleep(Duration::from_millis(1));
    }

    handle.join().unwrap();
}
thread::spawn: 1
main: 1
thread::spawn: 2
main: 2
thread::spawn: 3
thread::spawn: 4
获取返回值
use std::thread;
use std::time::Duration;

fn main() {
    let handle = thread::spawn(|| {
        for i in 1..5 {
            println!("thread::spawn: {}", i);
            thread::sleep(Duration::from_millis(1));
        }
        // 返回值
        "aaaa"
    });

    for i in 1..3 {
        println!("main: {}", i);
        thread::sleep(Duration::from_millis(1));
    }

    let s = handle.join().unwrap();
    println!("s: {}", s)
}
main: 1
thread::spawn: 1
main: 2
thread::spawn: 2
thread::spawn: 3
thread::spawn: 4
s: aaaa
获取线程信息

子线程内部获取线程信息:thread::current()

use std::thread;
use std::time::Duration;

fn main() {
    let handle = thread::spawn(|| {
        thread::sleep(Duration::from_secs(2));
    });

    let t = handle.thread();
    println!("t {:?}", t);

    println!("t {:?}", t.id()); // 获取线程ID
    println!("t {:?}", t.name()); // 获取线程名称

    handle.join().unwrap();
}
t Thread { id: ThreadId(2), name: None, .. }
t ThreadId(2)
t None

丢弃handle

丢弃handle,子线程还是会执行。直到程序退出时,所有的子线程被强制停止

  • 丢弃handle只是放弃控制,不等于终止线程
use std::thread;
use std::time::Duration;

fn main() {
    {
        let handle = thread::spawn(|| {
            for i in 1..5 {
                println!("spawned thread: {}", i);
                thread::sleep(Duration::from_millis(1));
            }

        });
        // 离开作用域handle被丢弃
    }
    // 睡的比子线程长
    thread::sleep(Duration::from_secs(5));
}
spawned thread: 1
spawned thread: 2
spawned thread: 3
spawned thread: 4

thread::Builder创建

new创建

use std::thread;

fn main() {
    let builder = thread::Builder::new();

    let handler = builder.spawn(|| {
        // 线程代码
    }).unwrap();

    handler.join().unwrap();
}

设置参数

use std::thread;

fn main() {
    let builder = thread::Builder::new()
        .name("my_thread".to_string())
        .stack_size(1024 * 1024);

    let handler = builder.spawn(|| {
        // 线程代码
        println!("{:?}", thread::current());
    }).unwrap();

    handler.join().unwrap();
}
Thread { id: ThreadId(2), name: Some("my_thread"), .. }

传递参数

使用move关键字来获取参数所有权

  • Copy类型: 实际复制
  • Clone类型: 调用 clone
  • 非Copy类型: 移动所有权

thread::spawn传参

use std::thread;

fn main() {
    let value = 42;
    let text = "Hello".to_string();
    
    // 使用 move 关键字传递参数
    let handle = thread::spawn(move || {
        println!("Value: {}, Text: {}", value, text);
    });
    
    handle.join().unwrap();
}
Value: 42, Text: Hello

builder.spawn传参

use std::thread;

fn main() {
    let value = 42;
    let text = "Hello".to_string();
    
    let handle = thread::Builder::new()
        .name("parameter-thread".to_string())
        .spawn(move || {
            println!("Value: {}, Text: {}", value, text);
        })
        .unwrap();
    
    handle.join().unwrap();
}
Value: 42, Text: Hello

在spawn调用函数

无参函数

thread::spawn

use std::thread;


fn test_thread() {
    println!("Hello from a thread!");
}

fn main() {
    let handle = thread::spawn(test_thread);
    
    handle.join().unwrap();
}

thread::Builder

use std::thread;


fn test_thread() {
    println!("Hello from a thread!");
}

fn main() {
    let handle = thread::Builder::new()
        .name("parameter-thread".to_string())
        .spawn(test_thread)
        .unwrap();
    
    handle.join().unwrap();
}

有参函数

thread::spawn

use std::thread;

fn test_thread(value: i32, text: String) {
    println!("Value: {}, Text: {}", value, text);
}

fn main() {
    let value = 42;
    let text = "Hello".to_string();
    
    // 使用 move 关键字传递参数
    let handle = thread::spawn(move || {
        test_thread(value, text);
    });
    
    handle.join().unwrap();
}

thread::Builder

use std::thread;

fn test_thread(value: i32, text: String) {
    println!("Value: {}, Text: {}", value, text);
}

fn main() {
    let value = 42;
    let text = "Hello World!".to_string();

    let handle = thread::Builder::new()
        .name("parameter-thread".to_string())
        .spawn(move || {
            test_thread(value, text);
        })
        .unwrap();

    handle.join().unwrap();
}

作用域线程

使用std::thread::scope创建的作用域线程,生命周期受特定作用域

  • 优点
    • 在作用域结束之前必须完成或终止,无需手动joinhandle
    • 安全的访问数据,如需复制或克隆

参数访问

访问thread::scope外部参数

在thread::scope之前的定义的参数都可以访问(借用)
可变不可变取决于外部定义

use std::thread;
use std::time::Duration;

fn main() {
    let data = vec![1, 2, 3, 4, 5];

    // 线程作用域
    thread::scope(|s| {
        // 在这个作用域内可以安全地借用外部数据
        s.spawn(|| {
            println!("线程作用域1: {:?}", data);
            thread::sleep(Duration::from_secs(3));
            println!("线程作用域1 end")
        });
    });

    println!("主线程: {:?}", data);
}
线程作用域1: [1, 2, 3, 4, 5]
线程作用域1 end
主线程: [1, 2, 3, 4, 5]

访问thread::scope内部参数

use std::thread;
use std::time::Duration;

fn main() {
    // 线程作用域
    thread::scope(|s| {
        // 在这个作用域内可以安全地借用外部数据

        // 设置scope内部参数
        let text = "hello world".to_string();

        // 访问内部参数需要时move
        s.spawn(move || {
            println!("线程作用域1: {:?}", text);
            thread::sleep(Duration::from_secs(3));
            println!("线程作用域1 end")
        });
    });
}
线程作用域1: "hello world"
线程作用域1 end

返回值

use std::thread;
use std::time::Duration;

fn main() {
    
    // 线程作用域
    let s = thread::scope(|s| {
        "aaa"
    });

    println!("{}", s);
}
aaa

并行处理

use std::thread;
use std::time::Duration;

fn main() {
    // 线程作用域
    thread::scope(|s| {
        s.spawn(|| {
            println!("s1 start");
            thread::sleep(Duration::from_secs(3)); // 随眠3秒
            println!("s1 end");
        });


        s.spawn(|| {
            println!("s2 start");
            thread::sleep(Duration::from_secs(1)); // 随眠1秒
            println!("s2 end");
        });


        s.spawn(|| {
            println!("s3 start");
            thread::sleep(Duration::from_secs(2)); // 随眠2秒
            println!("s3 end");
        });
    });
}
s1 start
s2 start
s3 start
s2 end
s3 end
s1 end

Builder的spawn_scoped

需要再thread::scope创建

use std::thread;

fn main() {
    let data = vec!["aa", "sss"];
    
    thread::scope(|s| {
        // spawn_scoped 需要满足 'scope 生命周期约束
        thread::Builder::new()
            .name("asd".to_string())
            .spawn_scoped(s, || {
                println!("Need move: {:?}", data);
            }).unwrap();
    });
}
Need move: ["aa", "sss"]

返回值

use std::thread;
use std::time::Duration;

fn main() {
    let data = "aaa";
    
    // 线程作用域
    thread::scope(|s| {
        let handle = thread::Builder::new()
            .name("aaa".to_string())
            .spawn_scoped(s, || {
                thread::sleep(Duration::from_secs(1));
                println!("hello world: {}", data);
                "okok"
            }).unwrap();
        
        println!("handle: {}", handle.join().unwrap());
    });
}
hello world: aaa
handle: okok

scope和spawn区别

特性 普通 thread::spawn thread::scope
生命周期安全 不安全,可能导致悬垂指针 安全,编译时保证
外部数据访问 需要 move 或 Arc 直接借用
线程管理 需要手动 join 自动等待所有线程
内存安全 需要额外同步原语 编译时检查
错误传播 需要显式处理 Panic 自动传播
性能开销 无额外开销 极小开销(几乎为零)
适用场景 长生命周期线程 短生命周期并行任务
posted @ 2026-04-15 21:27  lxd670  阅读(13)  评论(0)    收藏  举报