• C++并发编程 异步任务


    C++并发编程 异步任务

    异步任务 std::async

    (1) std::async 会返回一个 std::future 对象, 这个对象持有最终计算出来的结果. 当需要这个值时, 只需要调用对象的get()成员函数. 并且直到“期望”状态为就绪的情况下, 线程才会阻塞; 之后,返回计算结果. 

        std::future<int> answer = std::async([] {
            std::stringstream stm;
            stm << "future id:" << std::this_thread::get_id() << std::endl;
            std::cout << stm.str();
            int sum = 0;
            for (int i = 1; i <= 100; i++)
            {
                sum += i;
                std::cout << i << " ";
            }
            std::cout << std::endl;
            std::this_thread::sleep_for(std::chrono::seconds(1));  // 增加延迟(1s)
            return sum;
        });
        std::stringstream stm;
        stm << "main id:" << std::this_thread::get_id() << std::endl;
        std::cout << stm.str();
        std::cout << "answer is: " << answer.get() << std::endl; // 此时会被阻塞, 直到异步任务返回
        std::cout << "tag 2" << std::endl;

    (2) std::async 允许通过添加额外的调用参数, 向函数传递额外的参数.
      如果第一个参数是一个指向成员函数的指针, 第二个参数提供有这个函数成员类的具体对象(可以通过指针, 或者包装在 std::ref 中), 剩余的参数可作为成员函数的参数传入.
      否则, 随后的所有参数将作为函数的参数, 或作为指定可调用对象的第一个参数. 比如 std::thread, 当参数为右值(rvalues)时, 拷贝操作将使用移动的方式转移原始数据. 这就允许使用“只移动”类型作为函数对象和参数.

        class XFun {
        public:
            XFun() {}
            ~XFun() {}
    
            void f(const std::string& str) {
                std::stringstream stm;
                stm << "f called. " << this << "-->" << str << std::endl;
                std::cout << stm.str();
            }
            std::string g(const std::string& str) {
                std::stringstream stm;
                stm << str << "[--> add by function g] " << this;
                return stm.str();
            }
            //XFun& operator=(const XFun&) = delete;
            //XFun(const XFun&) = delete;
    
            void operator()(const std::string& str) {
                std::stringstream stm;
                stm << "operator() called. " << this << "-->" << str << std::endl;
                std::cout << stm.str();
            }
        };
        XFun x;
        std::cout << "addr of x:" << &x << std::endl;
        std::async(&XFun::f, &x, std::string("test f()"));
        std::future<std::string> f2 = std::async(&XFun::g, x, std::string("test g() temp")); // 创建一个 x 对象的副本传入, 删除赋值函数后, 将不能编译
        std::async(std::ref(x), std::string("test operator()"));
        std::async(XFun(), std::string("test operator() temp")); // 创建一个 XFun 的临时对象传入
        std::cout << f2.get() << std::endl;

    (3) 默认情况下, std::async 会启动一个新线程来完成任务, 但是也可以指定额外的执行方式:
      std::launch::defered 指定等到 wait 或 get 被调用时才执行.
      std::launch::async 指定必须到独立的线程中执行.
      默认为: std::launch::defered | std::launch::async

        auto f3 = std::async(std::launch::deferred, [] {
            std::stringstream stm;
            stm << "f3 called. TID:" << std::this_thread::get_id() << std::endl;
            std::cout << stm.str();
        });
        auto f4 = std::async(std::launch::async, [] {
            std::stringstream stm;
            stm << "f4 called. TID:" << std::this_thread::get_id() << std::endl;
            std::cout << stm.str();
        });
        std::stringstream stm;
        stm << "main. TID:" << std::this_thread::get_id() << std::endl;
        std::cout << stm.str();
        std::this_thread::sleep_for(std::chrono::seconds(1));
        f3.wait();
  • 相关阅读:
    【Java-JVM】定量分析解决OutOfMemoryError: PermGen space, 来看科学量化分析
    Oracle11g 主机身份证明问题
    html标签的嵌套规则
    提高程序员职场价值的10大技巧
    IT人应当知道的10个行业小内幕
    趣文:如果编程语言是车
    去除inline-block元素间间距的N种方法
    《大型网站SEO优化实践》学习分享
    如何通过预加载器提升网页加载速度
    网页爬虫及其用到的算法和数据结构
  • 原文地址:https://www.cnblogs.com/diysoul/p/5937115.html
Copyright © 2020-2023  润新知