packaged_task
包装起来的可调用对象还可以直接调用,从这个角度来讲,packaged_task
对象也是一个可调用对象,lambda
的直接调用。
#include <iostream> #include <future> using namespace std; int main(){ cout << "main started and the thread id is " << std::this_thread::get_id() << endl; //我们把函数mythread通过packaged_task包装起来。参数是一个int,返回值类型是int std::packaged_task<int(int)> mypt([](int num){ cout << "mythread() started and the thread id is " << std::this_thread::get_id() << endl; cout << "num is: " << num << endl; std::chrono::milliseconds dura(5000); // 休息五秒 std::this_thread::sleep_for(dura); cout << "mythread() ended and the thread id is " << std::this_thread::get_id() << endl; return 5; }); mypt(10); //std::thread mythread(std::ref(mypt), 10); // 线程直接开始执行,第二个参数为线程入口参数 //mythread.join(); //std::future对象里包含有线程入口函数的返回结果,这里result保存mythread返回的结果。 std::future<int> res = mypt.get_future(); cout << "res.get() is : " << res.get() << endl; cout << "main ended and the thread id is " << std::this_thread::get_id() << endl; }
还有一些加容器的骚操作:
#include <iostream> #include <future> #include <vector> using namespace std; vector<std::packaged_task<int(int)>> mytask; int main(){ cout << "main started and the thread id is " << std::this_thread::get_id() << endl; //我们把函数mythread通过packaged_task包装起来。参数是一个int,返回值类型是int std::packaged_task<int(int)> mypt([](int num){ cout << "mythread() started and the thread id is " << std::this_thread::get_id() << endl; cout << "num is: " << num << endl; std::chrono::milliseconds dura(5000); // 休息五秒 std::this_thread::sleep_for(dura); cout << "mythread() ended and the thread id is " << std::this_thread::get_id() << endl; return 5; }); mytask.push_back(std::move(mypt)); // 入容器,用了移动语意。 std::packaged_task<int(int)> mypt2; auto iter = mytask.begin(); mypt2 = std::move(*iter); // 移动语意。 mytask.erase(iter); // 删除第一个元素,后续代码已经不可以再使用iter了。 mypt2(10); std::future<int> res = mypt2.get_future(); cout << "res.get() is : " << res.get() << endl; cout << "main ended and the thread id is " << std::this_thread::get_id() << endl; }
程序输出结果为:
main started and the thread id is 0x1000e3d40 mythread() started and the thread id is 0x1000e3d40 num is: 10 mythread() ended and the thread id is 0x1000e3d40 res.get() is : 5 main ended and the thread id is 0x1000e3d40 Program ended with exit code: 0
std::promise
std::promise
,也是一个类模板,功能是:我们能够在某个线程中给它赋值,然后我们可以在其他线程中,把这个值取出来
#include <iostream> #include <future> #include <vector> using namespace std; void mythread(std::promise<int> &tmp, int calc){ cout << "mythread() started and the thread id is " << std::this_thread::get_id() << endl; std::chrono::milliseconds dura(5000); // 休息五秒 std::this_thread::sleep_for(dura); ++calc; // 假装有复杂的计算 tmp.set_value(calc); cout << "mythread() ended and the thread id is " << std::this_thread::get_id() << endl; } int main(){ cout << "main started and the thread id is " << std::this_thread::get_id() << endl; std::promise<int> myprom; std::thread t1(mythread, std::ref(myprom), 10); t1.join(); std::future<int> res = myprom.get_future(); // future和promise绑定在一起。 cout << "res.get() is : " << res.get() << endl; cout << "main ended and the thread id is " << std::this_thread::get_id() << endl; }
输出结果为:
main started and the thread id is 0x1000dfd40 mythread() started and the thread id is 0x16fe87000 mythread() ended and the thread id is 0x16fe87000 res.get() is : 11 main ended and the thread id is 0x1000dfd40 Program ended with exit code: 0 • 1 • 2 • 3 • 4 • 5 • 6
总结:通过promise
保存一个值,在将来某个时刻我们通过吧一个future
绑定到这个promise
上,来得到绑定的值。如果想把线程1
中的值传入到线程2
中去的话,可以采用如下方式:
#include <iostream> #include <future> #include <vector> using namespace std; void mythread(std::promise<int> &tmp, int calc){ cout << "mythread() started and the thread id is " << std::this_thread::get_id() << endl; std::chrono::milliseconds dura(5000); // 休息五秒 std::this_thread::sleep_for(dura); ++calc; // 假装有复杂的计算 tmp.set_value(calc); cout << "mythread() ended and the thread id is " << std::this_thread::get_id() << endl; } void mythread_other(std::future<int> &tmp){ cout << "mythread_other() started and the thread id is " << std::this_thread::get_id() << endl; std::chrono::milliseconds dura(5000); // 休息五秒 std::this_thread::sleep_for(dura); cout << "mythread_other tmp.get() is : " << tmp.get() << endl; cout << "mythread_other() ended and the thread id is " << std::this_thread::get_id() << endl; } int main(){ cout << "main started and the thread id is " << std::this_thread::get_id() << endl; std::promise<int> myprom; std::thread t1(mythread, std::ref(myprom), 10); t1.join(); std::future<int> res = myprom.get_future(); // future和promise绑定在一起。 std::thread t2(mythread_other, std::ref(res)); t2.join(); return 0; }
输出结果为:
main started and the thread id is 0x1000e7d40 mythread() started and the thread id is 0x16fe87000 mythread() ended and the thread id is 0x16fe87000 mythread_other() started and the thread id is 0x16fe87000 mythread_other tmp.get() is : 11 mythread_other() ended and the thread id is 0x16fe87000 Program ended with exit code: 0
std::future
卡住当前流程,等待std::async()
的异步任务运行一段时间,然后返回其状态std::future_status
。如果std::async()
的参数std::launch::deferred
(延迟执行),则不会卡住主流程。std::future_status
是枚举类型,表示异步任务的执行状态。类型的取值有:std::future_status::timeout
,std::future_status::ready
,std::future_status::deferred
。
#include <iostream> #include <future> using namespace std; int mythread() { cout << "mythread() started and the thread id is " << std::this_thread::get_id() << endl; std::chrono::milliseconds dura(5000); // 休息五秒 std::this_thread::sleep_for(dura); cout << "mythread() ended and the thread id is " << std::this_thread::get_id() << endl; return 5; } int main() { cout << "main started and the thread id is " << std::this_thread::get_id() << endl; std::future<int> res = std::async(mythread); // 创建一个线程并开始执行 cout << "continue ....." << endl; // std::future_status为枚举类型 std::future_status status = res.wait_for(std::chrono::seconds(1)); // 等待1s钟 if (status == std::future_status::timeout) { // 超时,表示线程还没有执行完,主线程等待1s钟,但是线程还没有执行完。 cout << "超时,线程还没有执行完。" << endl; } else if (status == std::future_status::ready) { cout << "超时,线程成功执行完毕。" << endl; cout << res.get() << endl; } else if (status == std::future_status::deferred) { // std::future<int> res = std::async(std::launch::deferred, mythread); // 创建一个线程并延迟到get时执行 cout << "超时,线程被延迟执行。" << endl; cout << res.get() << endl; } cout << "main ended and the thread id is " << std::this_thread::get_id() << endl; }
输出结果为:
std::shared_future
get()
只能使用一次,因为get()
函数的设计是一个移动语义,相当于将result
中的值移动到了复制对象中,再次get
就报告了异常。如果有多个线程想要获得别的线程处理完的结果的话,shared_future
就排上用场了。std::future
的get()
成员函数是转移数据。std::shared_future
的get()
成员函数是复制数据。
#include <thread> #include <iostream> #include <future> using namespace std; int mythread() { cout << "mythread() start" << "threadid = " << std::this_thread::get_id() << endl; std::chrono::milliseconds dura(5000); std::this_thread::sleep_for(dura); cout << "mythread() end" << "threadid = " << std::this_thread::get_id() << endl; return 5; } int main() { cout << "main" << "threadid = " << std::this_thread::get_id() << endl; std::packaged_task<int()> mypt(mythread); std::thread t1(std::ref(mypt)); std::future<int> result = mypt.get_future(); bool ifcanget = result.valid(); //判断future 中的值是不是一个有效值 std::shared_future<int> result_s(result.share()); //执行完毕后result_s里有值,而result里空了 //std::shared_future<int> result_s(std::move(result)); //通过get_future返回值直接构造一个shared_future对象 //std::shared_future<int> result_s(mypt.get_future()); t1.join(); auto myresult1 = result_s.get(); auto myresult2 = result_s.get(); cout << "good luck" << endl; return 0; }
或者通过通过get_future
返回值直接构造一个shared_future
对象:
#include <thread> #include <iostream> #include <future> using namespace std; int mythread() { cout << "mythread() start" << "threadid = " << std::this_thread::get_id() << endl; std::chrono::milliseconds dura(5000); std::this_thread::sleep_for(dura); cout << "mythread() end" << "threadid = " << std::this_thread::get_id() << endl; return 5; } int main() { cout << "main" << "threadid = " << std::this_thread::get_id() << endl; std::packaged_task<int()> mypt(mythread); std::thread t1(std::ref(mypt)); t1.join(); //std::future<int> result = mypt.get_future(); //bool ifcanget = result.valid(); //判断future 中的值是不是一个有效值 //std::shared_future<int> result_s(result.share()); //执行完毕后result_s里有值,而result里空了 //std::shared_future<int> result_s(std::move(result)); //通过get_future返回值直接构造一个shared_future对象 std::shared_future<int> result_s(mypt.get_future()); auto myresult1 = result_s.get(); auto myresult2 = result_s.get(); cout << "good luck" << endl; return 0; }