c++11多线程之packaged_task<>介绍与实例
本節(jié)討論c++11中std::packaged_task的特性與使用方法
std::packaged_task<>
std::packaged_task<>是一個(gè)類模板,代表一個(gè)異步任務(wù)。封裝了
1、可調(diào)用實(shí)體,即函數(shù),lambda函數(shù)或函數(shù)對(duì)象
2、一個(gè)共享狀態(tài),通過關(guān)聯(lián)的回調(diào)來存儲(chǔ)返回的值或拋出的異常。
現(xiàn)在我們想在一個(gè)單獨(dú)的線程中執(zhí)行該函數(shù),但是我們?nèi)绻谄渌€程結(jié)束的情況下在主線程中獲取結(jié)果或異常返回?
一種方法是更改函數(shù)聲明并在函數(shù)中傳遞std::promise。在傳遞線程函數(shù)中的std::promise<>對(duì)象之前,將相關(guān)的std::future<>從中取出并保存在主線程中。現(xiàn)在,在線程函數(shù)返回其值之前,應(yīng)該在傳入的std::promise參數(shù)中設(shè)置它,所以它可以在主線程的相關(guān)std::future對(duì)象中使用。參考第八節(jié)
******************************************
但是,如果我們使用std::packaged_task<>,則可以避免創(chuàng)建std::promise和更改函數(shù)代碼。
使用packaged_task<>創(chuàng)建異步任務(wù)
std::packaged_task<>可以包裝一個(gè)標(biāo)準(zhǔn)函數(shù),使其適用于作為異步功能運(yùn)行。
當(dāng)std::packaged_task<>在一個(gè)單獨(dú)的線程中運(yùn)行時(shí),它會(huì)調(diào)用相關(guān)的回調(diào)函數(shù),并將返回值或異常存儲(chǔ)在其內(nèi)部共享狀態(tài)中。該值可以通過std :: future <>對(duì)象在其他線程或主函數(shù)中訪問。
從上面提到的函數(shù)創(chuàng)建一個(gè)packaged_task<>,運(yùn)行于獨(dú)立的線程并從其future<>對(duì)象獲取返回值。創(chuàng)建std::packaged_task<> 對(duì)象
std::packaged_task<>對(duì)象是一個(gè)類模板,因此我們需要將模板參數(shù)傳遞給packaged_task<>,即可調(diào)用函數(shù)的類型。
?
獲取future對(duì)象
//從packaged_task<>獲取相關(guān)future<> std::future<std::string> result = task.get_future();?傳遞packaged_task<>給線程
std::packaged_task<>可移動(dòng),但是不可復(fù)制,所以我們需要將它傳遞給線程
//傳遞packaged_task<>給線程以異步運(yùn)行 std::thread th(std::move(task), "Arg");由于packaged_task只可以移動(dòng),不可以復(fù)制,因此我們?cè)趯⑺苿?dòng)到線程之前從它那里取出了 std::future<>對(duì)象。
線程將會(huì)執(zhí)行這個(gè)任務(wù),該任務(wù)在內(nèi)部調(diào)用相關(guān)的可調(diào)用實(shí)體,例如我們的函數(shù)getDataFromDB()。
當(dāng)這個(gè)函數(shù)給出返回值時(shí),std::packaged_task<>將其設(shè)置為關(guān)聯(lián)的共享狀態(tài),getDataFromDB()返回的結(jié)果或異常最終會(huì)在關(guān)聯(lián)的未來對(duì)象中可用。
get()函數(shù)將會(huì)阻塞調(diào)用線程,直到有可調(diào)用的實(shí)體返回,并且std::packaged_task<>將數(shù)據(jù)設(shè)置為其可共享的狀態(tài)。
完整的例子如下:
#include <iostream> #include <thread> #include <future> #include <string>//從DB獲取數(shù)據(jù) std::string getDataFromDB(std::string token) {//獲取數(shù)據(jù)std::string data = "Data fetched from DB by Filter :: " + token;return data; }int main() {//創(chuàng)建封裝回調(diào)函數(shù)的packaged_task<>std::packaged_task<std::string(std::string)> task(getDataFromDB);//從packaged_task<>獲取相關(guān)的future<>std::future<std::string> result = task.get_future();//將packaged_task傳遞給線程以異步運(yùn)行std::thread th(std::move(task), "Arg");//join線程,阻塞直到線程完成時(shí)返回th.join();//獲取packaged_task<>的結(jié)果,即getDataFromDB()的返回值std::string data = result.get();std::cout << data << std::endl;return 0; }?輸出:
Data fetched from DB by Filter :: Arg我們可以在同一行,用lambda函數(shù)或函數(shù)對(duì)象創(chuàng)建一個(gè)packaged_task
?使用lambda函數(shù)創(chuàng)建packaged_task
#include <iostream> #include <thread> #include <future> #include <string>int main() {//創(chuàng)建封裝了lambda函數(shù)的packaged_task<>std::packaged_task<std::string(std::string)> task([](std::string token) {std::string data = "Data From " + token;return data;});//從packaged_task<>獲取相關(guān)的future<>std::future<std::string> result = task.get_future();//將packaged_task傳遞給線程以異步運(yùn)行std::thread th(std::move(task), "Arg");//join線程,阻塞直到線程完成時(shí)返回th.join();//獲取packaged_task<>的結(jié)果,即getDataFromDB()的返回值std::string data = result.get();std::cout << data << std::endl;return 0; }?輸出:
Data fetched from DB by Filter :: Arg使用函數(shù)對(duì)象創(chuàng)建packaged_task
#include <iostream> #include <thread> #include <future> #include <string>//從DB獲取數(shù)據(jù)的函數(shù)對(duì)象 struct DBDataFetcher {std::string operator ()(std::string token) {std::string data = "Data From " + token;return data;} };int main() {//使用函數(shù)對(duì)象創(chuàng)建packaged_taskstd::packaged_task<std::string(std::string)> task(std::move(DBDataFetcher()));//從packaged_task<>獲取相關(guān)的future<>std::future<std::string> result = task.get_future();//將packaged_task傳遞給線程以異步運(yùn)行std::thread th(std::move(task), "Arg");//join線程,阻塞直到線程完成時(shí)返回th.join();//獲取packaged_task<>的結(jié)果,即getDataFromDB()的返回值std::string data = result.get();std::cout << data << std::endl;return 0; }?輸出:
Data fetched from DB by Filter :: Arg原文鏈接:https://blog.csdn.net/lijinqi1987/article/details/78909524
總結(jié)
以上是生活随笔為你收集整理的c++11多线程之packaged_task<>介绍与实例的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 博通第一财季营收 89.15 亿美元,净
- 下一篇: 香港科技大学允许学生有限度使用 Chat