Skip to content

多线程

闭包

Rust中,闭包(Closure)是一种函数对象。

闭包的使用场景:

  • 迭代器:迭代器需要返回一个函数对象,用于迭代。
  • 事件处理:在事件处理中,闭包可以作为回调函数,用于处理事件。
  • 线程:在多线程中,闭包可以作为线程函数,用于创建线程。
rust
fn main() {
    let add = |a, b| a + b;
    println!("{}", add(1, 2));
}
rust
fn main() {
    let a = 1;
    let b = 2;

    // Fn闭包:通过引用捕获变量(不可变借用)
    let add = |x| a + x;

    // FnMut闭包:通过可变引用捕获变量(可变借用)
    let mut multiply = |x| {
        a * b * x
    };

    // FnOnce闭包:通过值捕获外部变量(所有权转移)
    let divide = move |x| x / b;

    println!("{}", add(3));
    println!("{}", multiply(3));
    println!("{}", divide(3));
}
rust
// 函数参数 (推荐此种写法)
fn apply<F>(f: F)
where
    F: Fn(),
{
    f();
}

// 返回闭包
fn create_closure() -> impl Fn() {
    let x = 5;
    move || println!("the value of x is {}", x)
}

fn main() {

    // 闭包作为参数
    let print_hello = || println!("hello, world!");
    apply(print_hello);

    // 返回闭包
    let closure = create_closure();
    closure();
}

多线程

简单示例

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

fn main() {
    let handle = thread::spawn(|| {
        for i in 1..10 {
            println!("hi number {} from the spawned thread!", i);
            thread::sleep(Duration::from_millis(1));
        }
    });
    for i in 1..5 {
        println!("hi number {} from the main thread!", i);
        thread::sleep(Duration::from_millis(1));
    }
}
bash
hi number 1 from the main thread!
hi number 2 from the main thread!
hi number 1 from the spawned thread!
hi number 2 from the spawned thread!
hi number 3 from the spawned thread!
hi number 4 from the spawned thread!
hi number 5 from the spawned thread!
hi number 6 from the spawned thread!
hi number 7 from the spawned thread!
hi number 8 from the spawned thread!
hi number 9 from the spawned thread!
hi number 3 from the main thread!
hi number 4 from the main thread!
bash
hi number 1 from the main thread!
hi number 2 from the main thread!
hi number 3 from the main thread!
hi number 4 from the main thread!
hi number 1 from the spawned thread!

通过Builder构建线程

rust
use std::thread;
use std::time::Duration;
fn main() {
    let handle = thread::Builder::new()
        .name("my-thread".to_string())      // 设置线程名称
        .stack_size(10 * 1024)         // 设置线程栈大小
        .spawn(|| {
            for i in 1..5 {
                println!("hi number {} from the spawned thread!", i);
                thread::sleep(Duration::from_millis(1));
            }
        });

    // 等待线程结束
    handle.unwrap().join().unwrap();
}
bash
hi number 1 from the spawned thread!
hi number 2 from the spawned thread!
hi number 3 from the spawned thread!
hi number 4 from the spawned thread!

子线程传值给主线程

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

fn main() {
    let sub_thread = thread::spawn(|| {
        println!("sub thread");
        println!("sub thread sleep 2 sec");
        thread::sleep(Duration::from_secs(2));
        println!("sub thread end");
        "hello"
    });
    let result = sub_thread.join().unwrap();
    println!("{}", result); // hello
}
rust
use std::thread;
fn my_func(n: u32) -> u32 {
    n + 1
}
fn main() {
    let handle = thread::spawn(|| my_func(1));
    let result = handle.join().expect("Cloud not join thread");
    println!("{}", result);
}

使用其他线程数据

rust
use std::thread;
fn main() {
    let data = "hello";
    let handle = thread::spawn(|| {
        println!("data: {}", data);
        // 编译不通过
        // help: to force the closure to take ownership of `data` (and any other referenced variables), use the `move` keyword
    });
    handle.join().unwrap();
}
rust
use std::thread;
fn main() {
    let data = "hello";
    let handle = thread::spawn(move || {
        println!("data: {}", data);
    });
    handle.join().unwrap();
}
rust
use std::thread;
fn main() {
    let v = vec![1, 3, 5, 7, 9, 11];
    let mut items = Vec::new();
    for i in v {
    
        // 这里必须添加move,转移所有权 
        let t = thread::spawn(move || {
            i * i
        });
        items.push(t);
    }

    // 执行
    for item in items {
        println!("{:?}", item.join().unwrap());
    }
}

线程函数

rust
use std::thread;

// 斐波那契数列
fn fibonacci(n: u64) -> u64 {
    match n {
        0 => 0,
        1 => 1,
        _ => fibonacci(n - 1) + fibonacci(n - 2),
    }
}

fn main() {
    let handle = thread::spawn(|| {
        let f = fibonacci(20);
        println!("fibonacci(20) = {}", f);
        f
    });
    println!("main thread");
    let v = handle.join().expect("thread panicked");
    println!("main thread end");
    println!("the value is {}", v);
}

获取线程信息

rust
fn main() {
    println!("{}", std::thread::available_parallelism().unwrap())
}
rust
    // 主线程ID
    println!("{:?}", std::thread::current().id());  // ThreadId(1)

    let handle = std::thread::spawn(|| {
        
        // 子线程ID
        println!("{:?}", std::thread::current().id());  // ThreadId(2)
    });

    handle.join().unwrap();

线程间通信

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

fn main() {
    // Mutex 互斥锁
    // Arc 原子引用计数器
    let counter = Arc::new(Mutex::new(0));
    let mut handles = vec![];
    for _ in 0..10 {
        // 引用计数
        let counter = Arc::clone(&counter);
        let handle = thread::spawn(move || {
            // 获取Mutex锁
            let mut num = counter.lock().unwrap();
            // 修改计数器的值
            *num += 1;
        });
        handles.push(handle);
    }
    for handle in handles {
        handle.join().unwrap();
    }
    println!("Result: {}", *counter.lock().unwrap());
}

人生感悟