Skip to content

4.多线程

一、创建一个线程

rust
use std::{thread, time::Duration};

fn main() {
    thread::spawn(move || {
        for item in 0..10 {
            println!("子线程: {}", item);
        };
    });

    for item in 0..10 {
        println!("主线程: {}", item);

        // 延迟一毫秒,如果不延迟,可能子线程还没执行,主线程就结束了
        thread::sleep(Duration::from_millis(1));
    };
}
use std::{thread, time::Duration};

fn main() {
    thread::spawn(move || {
        for item in 0..10 {
            println!("子线程: {}", item);
        };
    });

    for item in 0..10 {
        println!("主线程: {}", item);

        // 延迟一毫秒,如果不延迟,可能子线程还没执行,主线程就结束了
        thread::sleep(Duration::from_millis(1));
    };
}

使用thread::spawn 可以创建一个子线程,另外主线程需要延迟一毫秒,如果不延迟,可能子线程还没执行,主线程就结束了

二、等待子线程结束

rust
use std::{thread, time::Duration};

fn main() {
    let handle = thread::spawn(move || {
        for item in 0..10 {
            println!("子线程: {}", item);
        };
    });

    handle.join().unwrap();

    for item in 0..10 {
        println!("主线程: {}", item);

        // 延迟一毫秒,如果不延迟,可能子线程还没执行,主线程就结束了
        thread::sleep(Duration::from_millis(1));
    };
}
use std::{thread, time::Duration};

fn main() {
    let handle = thread::spawn(move || {
        for item in 0..10 {
            println!("子线程: {}", item);
        };
    });

    handle.join().unwrap();

    for item in 0..10 {
        println!("主线程: {}", item);

        // 延迟一毫秒,如果不延迟,可能子线程还没执行,主线程就结束了
        thread::sleep(Duration::from_millis(1));
    };
}

调用 handle.join().unwrap(), 可以等待handle对应的子线程结束后执行。

三、使用move转移线程外的所有权

如果不使用move关键字,有可能存在子线程还没执行完,主线程已经结束的情况,这种情况下arr的生命周期无法保证能活到子线程结束,所以需要move来转移所有权到子线程中

rust
fn main() {
    let arr = [1;10];
    let handle = thread::spawn(move || { // [!code  ++]
        for item in 0..10 {
            println!("子线程: {}", arr[item]);
            thread::sleep(Duration::from_millis(100))
        };
    });


    handle.join().unwrap();

    for item in 0..10 {
        println!("主线程: {}", item);

        // 延迟一毫秒,如果不延迟,可能子线程还没执行,主线程就结束了
        thread::sleep(Duration::from_millis(1));
    };

    println!("主线程结束");
}
fn main() {
    let arr = [1;10];
    let handle = thread::spawn(move || { // [!code  ++]
        for item in 0..10 {
            println!("子线程: {}", arr[item]);
            thread::sleep(Duration::from_millis(100))
        };
    });


    handle.join().unwrap();

    for item in 0..10 {
        println!("主线程: {}", item);

        // 延迟一毫秒,如果不延迟,可能子线程还没执行,主线程就结束了
        thread::sleep(Duration::from_millis(1));
    };

    println!("主线程结束");
}

调用 handle.join().unwrap(), 可以等待handle对应的子线程结束后执行。

四、创建线程的性能

创建一个线程大概需要 0.24 毫秒,随着线程的变多,这个值会变得更大,所以线程不要创建太多

五、线程屏障

可以使用 Barrier 让多个线程都执行到某个点后,才继续一起往后执行:

rust
use std::sync::{Arc, Barrier};
use std::thread;

fn main() {
    // 创建6个大小的容器
    let mut handles = Vec::with_capacity(6);
    // 创建6个屏障
    let barrier = Arc::new(Barrier::new(6));

    for _ in 0..6 {
        // 获取屏障
        let b = barrier.clone();
        // 收集hande
        handles.push(thread::spawn(move|| {
            println!("before wait");
            b.wait();
            println!("after wait");
        }));
    }

    // 等待6个线程执行完毕
    for handle in handles {
        handle.join().unwrap();
    }
}
use std::sync::{Arc, Barrier};
use std::thread;

fn main() {
    // 创建6个大小的容器
    let mut handles = Vec::with_capacity(6);
    // 创建6个屏障
    let barrier = Arc::new(Barrier::new(6));

    for _ in 0..6 {
        // 获取屏障
        let b = barrier.clone();
        // 收集hande
        handles.push(thread::spawn(move|| {
            println!("before wait");
            b.wait();
            println!("after wait");
        }));
    }

    // 等待6个线程执行完毕
    for handle in handles {
        handle.join().unwrap();
    }
}