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.唤醒所有等待线程

接下来运行看一下结果:

相关推荐
冷崖1 小时前
MySQL异步连接池的学习(五)
学习·mysql
知识分享小能手1 小时前
Vue3 学习教程,从入门到精通,Axios 在 Vue 3 中的使用指南(37)
前端·javascript·vue.js·学习·typescript·vue·vue3
七七&5564 小时前
2024年08月13日 Go生态洞察:Go 1.23 发布与全面深度解读
开发语言·网络·golang
java坤坤4 小时前
GoLand 项目从 0 到 1:第八天 ——GORM 命名策略陷阱与 Go 项目启动慢问题攻坚
开发语言·后端·golang
元清加油4 小时前
【Golang】:函数和包
服务器·开发语言·网络·后端·网络协议·golang
健康平安的活着5 小时前
java之 junit4单元测试Mockito的使用
java·开发语言·单元测试
焄塰6 小时前
Ansible 管理变量和事实
学习·centos·ansible
DjangoJason6 小时前
C++ 仿RabbitMQ实现消息队列项目
开发语言·c++·rabbitmq
oe10197 小时前
读From GPT-2 to gpt-oss: Analyzing the Architectural Advances(续)
笔记·gpt·学习
m0_480502647 小时前
Rust 入门 KV存储HashMap (十七)
java·开发语言·rust