rust学习(模拟Future)

一.future结构体

rust 复制代码
//声明
trait DefaultValue {//1
    fn getDefault()->Self;
}
struct MFuture<T> where T:DefaultValue + Copy{
    mutex:Mutex<(bool,T)>,//2
    cond:Condvar//3
}

struct MTask<T> where T:DefaultValue + Copy{
    future:Arc<MFuture<T>>,//4
    func:Box<dyn Fn()-> T + 'static + Send>,//5
}
//实现
impl DefaultValue for i32 {//6
    fn getDefault()->Self {
        0
    }
}

1.DefaultValue主要是为了初始化future的时候默认值需要赋值。没有办法,强行加了一个这个接口。

2.MFuture::mutex主要存储了一个元,包含了(是否完成,结果)这2项目

3.MFuture::cond主要是用来通知wait数据的线程。

4.MTask::future:存储了future的信息,用了智能指针,主要是等待线程需要持有一份,处理线程也需要持有一份,2个线程是通过future里面的cond来唤醒

5.MTask::func:存储了lambda函数

6.为I32实现了默认值的接口,方便后面初始化的时候获取默认值。

二.future实现

rust 复制代码
impl <T>MFuture<T> where T:DefaultValue + Copy{
    fn get(&self)-> T {
        loop {
            let mut complete = self.mutex.lock().unwrap();
            if complete.0.eq(&true) {
               return complete.1;
            } else {
                self.cond.wait(complete);
            }
        }
    }
}

原理比较简单,从future中获取数据元,如果元组第一个为true,则表明计算完成,直接返回数据,否则就调用condvar来等待。

三.模拟场景

线程1->list放入各种lambda函数

线程2->从list取出lambda函数,计算后将结果存放到future

线程1:

rust 复制代码
let mut list: Arc<Mutex<Vec<MTask<i32>>>> = Arc::new(Mutex::new(Vec::<MTask<i32>>::new()));//1
    
    let mut closure1 = list.clone();
    thread::spawn(move || {
        let mut count = 0;
        loop {
            thread::sleep(Duration::from_secs(1));

            let ll = || {
                println!("fn start");
                thread::sleep(Duration::from_secs(1));
                println!("fn finish start");
                123
            };//2

            let future = Arc::new(MFuture {
                mutex:Mutex::new((false,i32::getDefault())),
                cond:Condvar::new()
            }); //3

            let task = MTask {
                future:future.clone(),
                func:Box::new(ll)
            };//4

            {
                let mut l = closure1.lock().unwrap();
                l.push(task);
            } //5

            let f1 = future.clone();
            println!("v is {}",f1.get());//6
        }
    });

1.创建一个队列用来存放所有的task,类似一个生产者/消费者模型。

2.创建一个lambda函数,这里简单写了一个直接返回i32的函数,实际场景可能会是比较负责的函数。

3.生成一个future,这里i32::getDefault()获取默认数据,模板玩的不溜,这里直接写死了。照理应该不需要指定i32.

4.将回调函数保存下来,注意,这里是用Box来保存的。

5.将这个task推到队列里面

6.调用get函数 ,如果没有计算完,等待。哈哈。

线程2:

rust 复制代码
let mut closure2 = list.clone();
    thread::spawn(move || {
        loop {
            thread::sleep(Duration::from_millis(500));
            let mut v = closure2.lock().unwrap();
            if v.len() == 0 {
                continue;
            }

            let mut vv = v.pop().unwrap();
            let ret = (vv.func)();//1
            let mut comp = vv.future.mutex.lock().unwrap();
            comp.0 = true;//2
            comp.1 = ret;//2
            vv.future.cond.notify_all();//3
        }
    }).join();

1.调用线程1中保存的lambda函数,执行获取结果

2.更新future中用来保存运算结果的数据元。comp.0表示是否计算完成,comp.1存放运算结果

3.唤醒所有等待线程

接下来运行看一下结果:

相关推荐
Alive~o.0几秒前
Go语言进阶&依赖管理
开发语言·后端·golang
Chef_Chen2 分钟前
从0开始学习机器学习--Day33--机器学习阶段总结
人工智能·学习·机器学习
花海少爷2 分钟前
第十章 JavaScript的应用课后习题
开发语言·javascript·ecmascript
手握风云-3 分钟前
数据结构(Java版)第二期:包装类和泛型
java·开发语言·数据结构
喵叔哟23 分钟前
重构代码中引入外部方法和引入本地扩展的区别
java·开发语言·重构
尘浮生29 分钟前
Java项目实战II基于微信小程序的电影院买票选座系统(开发文档+数据库+源码)
java·开发语言·数据库·微信小程序·小程序·maven·intellij-idea
hopetomorrow42 分钟前
学习路之压力测试--jmeter安装教程
学习·jmeter·压力测试
hopetomorrow43 分钟前
学习路之PHP--使用GROUP BY 发生错误 SELECT list is not in GROUP BY clause .......... 解决
开发语言·学习·php
小牛itbull1 小时前
ReactPress vs VuePress vs WordPress
开发语言·javascript·reactpress
请叫我欧皇i1 小时前
html本地离线引入vant和vue2(详细步骤)
开发语言·前端·javascript