std::promise和std::future的用法
1、std::promise和std::future注意用来在线程间传递数据不用手工同步来传递数据。2、在之前通过传递引用来传递数据也能达到上述效果但是需要手动同步否则获取到不可预测的结果。#include iostream #include thread void func(std::vectorint myVector,int result) { auto it std::max_element(myVector.begin(),myVector.end()); result *it; } int main() { int result 0; std::vectorint myVector{1,2,3,6,7,8,99,12}; std::thread thread01(func,std::ref(myVector),std::ref(result));//创建一个子线程调用func并把结果放引用参数中 thread01.join();//这里要手动同步等待线程结束才能下一句正确打印 std::cout result std::endl;//如果上面没有join就会得到错误的结果。 return 0; }3、一种更安全的线程间传递数据的方式使用promise设定值使用promise.get_future关联futrue对象通过future.get()来获取promise设定的值而且future的get自动同步promise如果promise的set未完成会自动阻塞并等待直到set完成。//更好的传递数据的方式 #include iostream #include thread #include vector #include chrono #include future #include algorithm void func(std::vectorint myVector,std::promiseint pro) { std::this_thread::sleep_for(std::chrono::seconds(2));//模拟子线程执行需要2秒 auto it std::max_element(myVector.begin(),myVector.end()); pro.set_value(*it);//子线程用来设定结果 } int main() { std::vectorint myVector{1,3,6,7,8,2,4}; std::promiseint pro;//创建一个promise对象 std::futureint fut pro.get_future();//创建一个future对象并关联到promise std::thread thread01(func,std::ref(myVector),std::ref(pro)); int result fut.get();//会自动等待promise.set()结束 std::cout result std::endl; thread01.join(); return 0; }4、在函数参数中type表示参数可以接受一个右值引用对象即参数可以接受一个临时对象针对不可复制对象传递参数时需要使用std::move方式传递转移对象的所有权。type表示接受一个引用对象如果对象也是不可复制对象需要使用std::ref()函数将对象进行包装为左值引用对象。#include iostream #include future #include thread #include vector #include algorithm #include chrono //线程函数 void find_max(const std::vectorint vec, std::promiseint prom)//接受一个promise右值引用对象 //void find_max(const std::vectorint vec, std::promiseint prom)//接受一个promise引用对象 { std::this_thread::sleep_for(std::chrono::seconds(2)); try { auto it std::max_element(vec.begin(), vec.end()); prom.set_value(*it);//设置结果 } catch (...) { prom.set_exception(std::current_exception());//设置异常结果 } } void findMin(std::vectorint myVector,int result) { auto it std::min_element(myVector.begin(), myVector.end()); result *it; } int main() { std::vectorint data{1,5,3,9,2}; std::promiseint prom;//主线程创建一个promise对象 std::futureint fut prom.get_future();//主线程通过调用get_future()获得与promise对象相关联的future对象 std::thread worker(find_max, std::cref(data), std::move(prom));//创建一个子线程传递数据和promise对象的右值引用 //std::thread worker(find_max, std::ref(data), std::ref(prom));//传递promise的左值引用对象 int result fut.get();//主线程通过调用future对象的get()方法获取结果如果子线程未完成计算主线程将会阻塞等待 std::cout Max element: result std::endl; int result2 0; std::thread thread02(findMin, std::ref(data), std::ref(result2)); thread02.join();//必须手动同步线程等待线程完成后才能访问result2 std::cout Min element: result2 std::endl; worker.join(); return 0; }5、以上2种方式都可以完成线程之间数据的传递推荐使用promise和future的方式这样自动线程同步而且不仅提供了设定值而且异常时可以设定异常promise.set_exception()来设定异常而且当不需要阻塞时可以使用wait_for() wait_until()来设定等待的时间特别适用于生产者消费者模式但注意的是promise只能set_value一次future也只能get一次。6、鉴于这种线程间通信传递数据方式只适合于“单次、异步任务的结果传递”不适合“持续生成和消费”的情形。C原生支持持续生成和消费者模式。如下#include iostream #include thread #include queue #include mutex #include condition_variable #include chrono // 简单的线程安全阻塞队列 templatetypename T class BlockingQueue { private: std::queueT queue_; std::mutex mtx_; std::condition_variable cv_producer_; // 通知生产者队列不满 std::condition_variable cv_consumer_; // 通知消费者队列不空 size_t max_size_; public: BlockingQueue(size_t max_size) : max_size_(max_size) {} // 生产者放入数据。如果队列满了就阻塞等待 void push(T item) { std::unique_lockstd::mutex lock(mtx_); cv_producer_.wait(lock, [this] { return queue_.size() max_size_; }); queue_.push(std::move(item)); std::cout [生产] 生产了一个数据队列大小: queue_.size() std::endl; cv_consumer_.notify_one(); // 叫醒一个正在等待的消费者 } // 消费者取出数据。如果队列空了就阻塞等待 T pop() { std::unique_lockstd::mutex lock(mtx_); cv_consumer_.wait(lock, [this] { return !queue_.empty(); }); T item std::move(queue_.front()); queue_.pop(); std::cout [消费] 消费了一个数据队列剩余: queue_.size() std::endl; cv_producer_.notify_one(); // 叫醒一个正在等待的生产者 return item; } }; // 使用示例 int main() { BlockingQueueint bq(5); // 容量为5的队列 // 生产者线程 std::thread producer([bq] { for (int i 0; i 20; i) { bq.push(i); std::this_thread::sleep_for(std::chrono::milliseconds(50)); } }); // 消费者线程 std::thread consumer([bq] { for (int i 0; i 20; i) { int val bq.pop(); std::this_thread::sleep_for(std::chrono::milliseconds(150)); // 消费慢一点 } }); producer.join(); consumer.join(); return 0; }
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2529338.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!