c++异步操作——std::future

1.参考资料

        

2.学习目的

        写一个可控的线程类,把一些时钟类,网络类,日志类,数据库类都继承于线程类,这样可以统一管理这些线程,也可以让这些类的操作不直接影响主流程。

3.开始学习

①类的作用

类模板 std::future 提供访问异步操作结果的机制:

  • 然后,异步操作的创建者能用各种方法查询、等待或从 std::future 提取值。若异步操作仍未提供值,则这些方法可能阻塞。
  • 异步操作准备好发送结果给创建者时,它能通过修改链接到创建者的 std::future 的共享状态(例如 std::promise::set_value )进行

②类的使用

#include <iostream>
#include <future>
#include <thread>
#include <chrono>

int test()
{
    std::this_thread::sleep_for(std::chrono::seconds(3));
    return 100;
}

int main()
{
    //-----------------------------------------------
    //std::future的基本用法
    //-----------------------------------------------
    //使用std::packaged_task包装函数
    std::packaged_task<int()> task1(&test);
    //std::packaged_task可以获取future
    std::future<int> f1 = task1.get_future();
    //在线程上运行
    std::thread(std::move(task1)).detach();

    std::cout << "-----------wait 和get的用法--------------" << std::endl;
    std::cout << "Waiting..." << std::endl;
    std::cout << "阻塞3秒:";
    //在这个位置会发生阻塞,直到产生结果
    f1.wait();
    //这里的f.get()与wait有类似的效果,
    //当结果没有产生的时候会发生阻塞,
    //有结果的时候会直接返回结果
    std::cout << "res = " << f1.get() << std::endl;

    //std::cout << "-----------wait_for的用法--------------" << std::endl;
    //---------------------------------------------------
    //wait_for和std::async的用法:
    //在wait_for中加入超时时间,当执行完成或者到了超时时间
    //的时候,wait_for跳出阻塞,返回对应的状态
    //--------------------------------------------------
    std::future<int> f2 = std::async(std::launch::async, &test);

    //-------------------------------------------------
    //std::future的三种状态
    //future_status::deferred   要计算结果的函数仍未启动
    //future_status::ready      结果就绪
    //future_status::timeout    已经过时限

    std::cout << "waiting..." << std::endl;
    std::future_status status;
    int i = 0;
    do {
        status = f2.wait_for(std::chrono::seconds(1));
        i++;
        std::cout << "阻塞" << i << "秒 :";
        if (status == std::future_status::deferred) {
            std::cout << "deferred" << std::endl;
        } else if (status == std::future_status::timeout) {
            std::cout << "timeout" << std::endl;
        } else if (status == std::future_status::ready) {
            std::cout << "ready!" << std::endl;
        }
    } while (status != std::future_status::ready); 

    std::cout << "res =" << f2.get() << std::endl;;
    std::cout << "-----------wait_until的用法--------------" << std::endl;
    //------------------------------------------------------
    //wait_until的用法,加入等待时间,当等待时间结束或者执行完成
    //的时候,wait_until跳出阻塞,返回对应的状态
    //-----------------------------------------------------
    std::packaged_task<int()> task3(&test);
    std::future<int> f3 = task3.get_future();
    std::thread(std::move(task3)).detach();

    std::cout << "waiting..." << std::endl;
    //等待时间是当前时间加1秒,
    std::cout << "阻塞1秒:";
    auto untilTime1 = std::chrono::system_clock::now() + std::chrono::seconds(1);
    auto status1 = f3.wait_until(untilTime1);
    if (status1 == std::future_status::deferred) {
        std::cout << "deferred" << std::endl;
    } else if (status1 == std::future_status::timeout) {
        std::cout << "timeout" << std::endl;
    } else if (status1 == std::future_status::ready) {
        std::cout << "ready!" << std::endl;
    }

    //阻塞了1秒再加2秒应该出结果了
    std::cout << "阻塞3秒:";
    auto untilTime2 = std::chrono::system_clock::now() + std::chrono::seconds(2);
    auto status2 = f3.wait_until(untilTime2);

    std::cout << "res =" << f3.get() << std::endl;

}

    4.总结

①比较容易忽略的坑

    在连接的时候需要加上 -lpthread 如果不加入的话,虽然可以编译链接过,但是执行的时候会出问题。

②初始化

    一共有三种初始化的方法,其中std::async代码最简洁,std::packaged_task相对复杂一些,另一种方法通过 std::promise 比较复杂,暂时没有看明白。后面有需求的时候研究一下。

③函数的使用

wait(),get(),wait_for()和wait_until()的调用都会被阻塞,wait()和get()是阻塞到完成操作,wait_for()是阻塞到设置的时间长度,wait_until()是阻塞到时间点。

④应用

可以通过future写一个单一线程,主线程可以把任务发放到这些单一线程上,这些线程在完成操作之后,把结果返给主线程,继续等待任务。

        

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值