美文网首页
浅谈C++异步

浅谈C++异步

作者: 陈道乐 | 来源:发表于2018-10-31 13:23 被阅读0次

    头文件 #include<future> ,在Linux下需要添加 -lpthread 参数

    std::async

    本质上是创建一个线程,使用传递的任务方法在线程中运行, 通过std::launch::async/deferred 来设置是否立即调用还是延迟调用

    std::future

    获得任务结果, 使用future的get方法,获得任务执行的返回值, 但是如果当前任务尚未执行, 任务会触发立即执行, 并且堵塞当前线程,直到任务完成

    方法

    • get() //获取任务返回结果,该方法只能调用一次, 使用后futrue变得不确定
    • wait() //等待任务完成
    • wait_for(dur) //等待一定时间或运行完成
    • wait_until(fp) //等待某一时刻或运行完成
    • share() //生成一个shared_future,shared_futrue类型允许使用第二次, 并且使用获得结果与第一次一样,如果有一场,抛出的异常也是一样的。

    * 范例1

    #include <iostream>
    #include <future>
    
    int main(int argc, char* args[])
    {
    
        //创建完成后线程实际上已经开始运行
        std::future<int> ret = std::async([](){
            std::cout << "Task Thread ID:" << std::this_thread::get_id() << std::endl;
            //假设这里是一个很费时间的一个操作
            return 0;
        });
    
        std::cout << "Main Thread ID:" << std::this_thread::get_id() << std::endl;
    
        //如果当前任务未完成的话,主线程会堵塞,当然我们也可以把堵塞的任务传递给其他线程做
        std::cout << "Ret:" << ret.get() << std::endl;
    
        return  0;
    }
    

    * 范例2

    多线程下的使用

    #include <iostream>
    #include <future>
    
    //任务方法
    void task(std::promise<int> &prom)
    {
        int ret;
        //假设这里是一个很费时间的一个操作
        ret = 4;
    
        prom.set_value_at_thread_exit(ret);
    }
    
    //打印任务结果
    void printRet(std::future<int> &future)
    {
        std::cout << "ret:" << future.get() << std::endl;
    }
    
    int main(int argc, char* args[])
    {
        std::promise<int> prom;
        std::future<int> future = prom.get_future();
    
        //创建线程执行任务
        std::thread t = std::thread(task, std::ref(prom));
        //创建线程接受任务执行结果
        std::thread t2 = std::thread(printRet, std::ref(future));
    
        //等待线程完成
        t.join();
        t2.join();
    
        return  0;
    }
    

    * 范例3

    参数传递

    #include <iostream>
    #include <future>
    
    int sum(int a, int b)
    {
        return  a + b;
    }
    
    int main(int argc, char* args[])
    {
    
        //创建完成后线程实际上已经开始运行,参数附加在末尾
        std::future<int> ret = std::async(sum, 1, 2);
    
        std::cout << "Main Thread ID:" << std::this_thread::get_id() << std::endl;
    
        //如果当前任务未完成的话,主线程会堵塞,当然我们也可以把堵塞的任务传递给其他线程做
        std::cout << "Ret:" << ret.get() << std::endl;
    
        return  0;
    }
    

    std::shared_future

    使用与futrue相似。,shared_futrue类型允许使用第二次, 并且使用获得结果与第一次一样,如果有一场,抛出的异常也是一样的
    std::shared_futrue f = std::async(task).share();

    std::packaged_task(重点)

    将任务打包, 好处是,可以手动触发何时执行任务

    #include <iostream>
    #include <future>
    
    int sum(int a, int b)
    {
        std::cout << "Task Thread ID:" << std::this_thread::get_id() << std::endl;
        return  a + b;
    }
    
    int main(int argc, char* args[])
    {
        //对任务进行封装
        std::packaged_task<int(int, int)> task(sum);
        //获取future
        std::future<int> future = task.get_future();
    
        //直接出发任务task(1, 2),但是任务处于调用线程中
        //移动到线程中执行异步任务
        std::thread t = std::thread(std::move(task), 1, 3);
    
        std::cout << "Main Thread ID:" << std::this_thread::get_id() << std::endl;
    
        std::cout << "Ret:" << future.get() << std::endl;
        t.join();
        return 0;
    }
    

    范例 4

    使用wait_for 等待任务完成

    #include <iostream>
    #include <future>
    
    double recursive(double a)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
        if ( a == 0)
        {
            return a;
        }
    
        return  recursive(a - 1) + a;
    }
    
    int main()
    {
        std::packaged_task<double(double)> task(recursive);
        std::future<double> future = task.get_future();
    
    
        //移动到线程中处理
        std::thread t = std::thread(std::move(task), 1000);
        std::thread t2 = std::thread([](std::future<double>& future){
            //等待线程完成执行
            while (future.wait_for(std::chrono::milliseconds(200)) == std::future_status::timeout)
            {
                std::cout << ".";
            }
            std::cout << "\n" << std::endl;
    
            std::cout << "result:" << future.get() << std::endl;
        }, std::ref(future));
    
        t.join();
        t2.join();
    
        return 0;
    }
    

    范例 5

    futrue共享状态在get调用后就解除,下次调用会发生报错。 但是使用shared_future的时候,get方法可调用多次,但是结果是一样的

    #include <iostream>
    #include <future>
    
    int do_work()
    {
        return 100;
    }
    
    int main()
    {
        std::future<int> future = std::async(do_work);
        //获取共享future
        std::shared_future<int> shared_future = future.share();
    
        //shared_future多次获取结果
        std::cout << "ret1:" << shared_future.get() << std::endl;
        std::cout << "ret2:" << shared_future.get() << std::endl;
        return 0;
    }
    

    相关文章

      网友评论

          本文标题:浅谈C++异步

          本文链接:https://www.haomeiwen.com/subject/zsyotqtx.html