0
点赞
收藏
分享

微信扫一扫

SpringBoot3整合Elasticsearch8.x之全面保姆级教程

WikongGuan 03-21 19:00 阅读 2

文章目录


前言


一、创建线程

Rust创建线程是通过thread::spawn函数来创建的,我们只要通过这个函数,并且传入一个闭包即可创建出一个线程。

以两个线程同时输出数字为例,主线程输出1到5,子线程输出1到10。其代码如下所示

    thread::spawn(|| {
        for i in 1..10 {
            println!("数字是:{},来自spawn创建的线程", i);
            thread::sleep(Duration::from_millis(1));
        }
    });
    for i in 1..5 {
        println!("数字是:{},来自主线程线程", i);
        thread::sleep(Duration::from_millis(1));
    }

这样就创建好一个线程了,执行效果如下图
从图中可以看出主线程输出了从1到4的数字编号,因为到了5的时候已经执行完毕了,但是子线程却是执行到了5,并没有向后执行,这是因为主线程已经结束了,此时会把子线程也销毁,简而言之就是子线程的生存周期超出了主线程的生存周期,主线程提前结束。

为了解决这个,就需要接收这个线程的返回值,然后调用join方法来让主线程等待子线程执行完毕再结束运行。

thread::spawn返回一个JoinHandle,其有一个join方法,可以让主线程等待该线程完毕后再结束。

处理以上的问题,因此对代码进行一下改动

    let handle =thread::spawn(|| {
        for i in 1..10 {
            println!("数字是:{},来自spawn创建的线程", i);
            thread::sleep(Duration::from_millis(1));
        }
    });
    
    for i in 1..5 {
        println!("数字是:{},来自主线程线程", i);
        thread::sleep(Duration::from_millis(1));
    }
    handle.join().unwrap();

此时代码正常运行,结果如下图所示
如果将handle.join().unwrap();放到主线程for循环之前则会出现同步运行的效果,如下图所示

move关键字主要的作用是用来避免在使用闭包的时候遇到的所有权问题的,它起到的一个作用就是在你代码有疑问时,会提示你代码哪里错了,为什么错了。当然,你也可以理解为捕获了外部的变量的所有权。

move关键字的使用是相当简单的,只要在闭包前面加上move就可以了,会自动进行变量的捕获。示例代码如下所示

let v = vec![1, 2, 3];
    let handle = thread::spawn(move || {
        println!("Here's a vector: {:?}", v);
    });
    handle.join().unwrap();

二、mpsc多生产者单消费者模型

mpsc多个生产者,单个消费者(multiple producer, single consumer)的缩写。简而言之,Rust 标准库实现信道的方式意味着一个信道可以有多个产生值的 发送(sending)端,但只能有一个消费这些值的 接收(receiving)端。

1.创建一个简单的模型

mpsc是通过mpsc::channel来创建的,返回一个发送者(tx),一个接收者(rx)。

创建一个简单的模型代码如下,发送端在线程内部发送一个字符串Hello,然后接收端接收这个字符串。

let (tx, rx) = mpsc::channel();
    thread::spawn(move || {
        let hello = String::from("Hello");
        tx.send(hello)
    });
    let received = rx.recv().unwrap();
    println!("接收到的数据是:{}", received)

代码运行效果如下

2.分批发送数据

在使用时,发送端可能会发送多次数据,或者是分批来发送数据,如果再使用

let received = rx.recv().unwrap();

来接收数据,则会起不到想要的效果,因为它只能接收一次,所以可以使用for循环来接收数据

for received in rx {
        println!("接收到的值: {}", received);
    }

这样只要是发送端发送的数据,接收端就都能接收到了,详细代码如下

    let (tx, rx) = mpsc::channel();
    thread::spawn(move || {
        let vals = vec![
            String::from("hi"),
            String::from("from"),
            String::from("the"),
            String::from("thread"),
        ];
        for val in vals {
            tx.send(val).unwrap();
            thread::sleep(Duration::from_secs(1));
        }
    });
    // 不再显式调用 recv 函数
    for received in rx {
        println!("接收到的值: {}", received);
    }

3. 使用clone来产生多个生产者

let (tx, rx) = mpsc::channel();
    
    let tx1 = tx.clone();
    thread::spawn(move || {
        let vals = vec![
            String::from("hi"),
            String::from("from"),
            String::from("the"),
            String::from("thread"),
        ];
    
        for val in vals {
            tx1.send(val).unwrap();
            thread::sleep(Duration::from_secs(1));
        }
    });
    
    thread::spawn(move || {
        let vals = vec![
            String::from("more"),
            String::from("messages"),
            String::from("for"),
            String::from("you"),
        ];
    
        for val in vals {
            tx.send(val).unwrap();
            thread::sleep(Duration::from_secs(1));
        }
    });
    
    for received in rx {
        println!("Got: {}", received);
    }

三、共享状态:互斥锁

如果你对多线程开发有所了解,就一定了解过锁的概念。

1. 创建一个简单的锁

let m = Mutex::new(5);
    {
        // 使用 lock 方法获取锁,以访问互斥器中的数据。
        // 如果另一个线程拥有锁,并且那个线程 panic 了,则 lock 调用会失败。
        // MutexGuard也提供了一个 Drop 实现当离开作用域时自动释放锁
        let mut num = m.lock().unwrap();
        *num = 6;
    }
    println!("Mutex:{:?}", m);

2. 使用互斥锁解决引用问题

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 || {
            let mut num = counter.lock().unwrap();
            *num +=1;
        });
        handles.push(handle);
    }
    for handle in handles {
        handle.join().unwrap()
    }
    println!("Result: {}", *counter.lock().unwrap());
举报

相关推荐

0 条评论