async,future,packaged_task,promise
阿新 • • 發佈:2018-12-21
一、std::async,std::future
建立後臺任務並返回值希望執行緒返回一個結果
std::async是個函式模板,用來啟動一個非同步任務,啟動起來返回std::future建立一個執行緒並開始執行對應的執行緒函式返回std::future
std::future物件裡面就有執行緒函式的返回結果,可能沒辦法馬上得到,
但是線上程執行完畢的時候,就會返回結果了
#include<future> using namespace std; int mythread() { cout << "mythread() start. thread id =" << std::this_thread::get_id() << endl; std::this_thread::sleep_for(2s);//休息2秒 cout << "mythread() end. thread id =" << std::this_thread::get_id() << endl; return 5; } int main() { cout << "main id = " << std::this_thread::get_id() << endl; std::future<int> result = std::async(mythread); cout << "continue.... " << endl; cout << result.get() << endl;//只能呼叫一次,呼叫多次報異常 }
可以通過額外向std::async()傳遞一個引數,該引數型別是std::launch型別(列舉型別),來達到一些特殊的目的。
比如std:launch::deferred:表示執行緒入口函式呼叫被延遲到std::future的wait()或者get()函式呼叫時才執行
如果沒呼叫get()或者wait(),那麼執行緒根本就沒有建立。
並且沒有新執行緒的建立,是在主執行緒裡執行的
class A { public: int mythread(int mypar) { cout << mypar << endl; cout << "mythread() start. thread id =" << std::this_thread::get_id() << endl; std::this_thread::sleep_for(2s);//休息2秒 cout << "mythread() end. thread id =" << std::this_thread::get_id() << endl; return 5; } }; int main() { A a; int tmpper = 12; cout << "main id = " << std::this_thread::get_id() << endl; std::future<int> result = std::async(std::launch::deferred,&A::mythread,&a,tmpper);//第二個是引用保證是原物件 cout << "continue.... " << endl; //cout << result.get() << endl; }
std::launch::async
則是建立一個子執行緒,並且立即執行。
async()函式預設的就是async。
std::packaged_task:打包任務,把任務包裝起來
是個類模板,模板引數是各種可呼叫物件。通過packaged_task來把各種可呼叫物件包裝起來,方便將來作為執行緒入口函式用來呼叫
#include<future> using namespace std; int mythread(int mypar) { cout << mypar << endl; cout << "mythread() start. thread id =" << std::this_thread::get_id() << endl; std::this_thread::sleep_for(2s);//休息2秒 cout << "mythread() end. thread id =" << std::this_thread::get_id() << endl; return 5; } int main() { cout << "main id = " << std::this_thread::get_id() << endl; std::packaged_task<int(int)> mypt(mythread); std::thread t1(std::ref(mypt),1); t1.join(); std::future<int> result = mypt.get_future(); cout << result.get() << endl; cout << "continue.... " << endl; }
#include<future>
using namespace std;
int main()
{
cout << "main id = " << std::this_thread::get_id() << endl;
//packaged_task包裝起來的可呼叫物件還可以直接呼叫,所以從這個角度來講,packaged_task物件也是一個可呼叫物件
std::packaged_task<int(int)> mypt([](int mypar) {
cout << mypar << endl;
cout << "mythread() start. thread id =" << std::this_thread::get_id() << endl;
std::this_thread::sleep_for(2s);//休息2秒
cout << "mythread() end. thread id =" << std::this_thread::get_id() << endl;
return 5;
});
mypt(105);//相當於函式呼叫
std::future<int> result = mypt.get_future();
cout << result.get() << endl;
cout << "continue.... " << endl;
return 0;
}
vector<packaged_task<int(int)>> mytasks;
int main()
{
cout << "main id = " << std::this_thread::get_id() << endl;
//packaged_task包裝起來的可呼叫物件還可以直接呼叫,所以從這個角度來講,packaged_task物件也是一個可呼叫物件
std::packaged_task<int(int)> mypt([](int mypar) {
cout << mypar << endl;
cout << "mythread() start. thread id =" << std::this_thread::get_id() << endl;
std::this_thread::sleep_for(2s);//休息2秒
cout << "mythread() end. thread id =" << std::this_thread::get_id() << endl;
return 5;
});
mytasks.push_back(std::move(mypt));//入容器,mypt為空
//...
std::packaged_task<int(int)>mypt2;
auto iter = mytasks.begin();
mypt2 = std::move(*iter);
mytasks.erase(iter);//刪除第一個元素,迭代器失效
mypt2(23);
std::future<int> result = mypt2.get_future();
cout << result.get() << endl;
cout << "continue.... " << endl;
return 0;
}
#include<future>
using namespace std;
//std::promise 類模板
//能夠在某個執行緒中給它賦值,然後在其他執行緒中把這個值取出來用。
//總結:通過promise儲存一個值,在將來某個時刻我們通過一個future繫結到這個promise來獲取這個繫結的值
void mythread(std::promise<int>&temp, int cal)
{
cal++;
this_thread::sleep_for(2s);
int result = cal;//儲存結果
temp.set_value(result);//結果儲存到temp物件中,
return;
}
void mythread2(std::future<int> &temp)
{
auto result = temp.get();
cout << "mythread2 result " << result << endl;
}
int main()
{
cout << "main id = " << std::this_thread::get_id() << endl;
//packaged_task包裝起來的可呼叫物件還可以直接呼叫,所以從這個角度來講,packaged_task物件也是一個可呼叫物件
std::promise<int>myprom;
std::thread t(mythread, std::ref(myprom), 180);
t.join();
//獲取結果值
std::future<int> fu1 = myprom.get_future();//獲取返回值
std::thread t2(mythread2, std::ref(fu1));
t2.join();
cout << "continue.... " << endl;
return 0;
}