淺談C++異步

頭文件 #include<future> 婆誓,在Linux下需要添加 -lpthread 參數

std::async

本質上是創(chuàng)建一個線程旦袋,使用傳遞的任務方法在線程中運行吸奴, 通過std::launch::async/deferred 來設置是否立即調用還是延遲調用

std::future

獲得任務結果, 使用future的get方法斩狱,獲得任務執(zhí)行的返回值网沾, 但是如果當前任務尚未執(zhí)行心软, 任務會觸發(fā)立即執(zhí)行壕吹, 并且堵塞當前線程,直到任務完成

方法

  • get() //獲取任務返回結果删铃,該方法只能調用一次, 使用后futrue變得不確定
  • wait() //等待任務完成
  • wait_for(dur) //等待一定時間或運行完成
  • wait_until(fp) //等待某一時刻或運行完成
  • share() //生成一個shared_future耳贬,shared_futrue類型允許使用第二次, 并且使用獲得結果與第一次一樣猎唁,如果有一場咒劲,拋出的異常也是一樣的。

* 范例1

#include <iostream>
#include <future>

int main(int argc, char* args[])
{

    //創(chuàng)建完成后線程實際上已經開始運行
    std::future<int> ret = std::async([](){
        std::cout << "Task Thread ID:" << std::this_thread::get_id() << std::endl;
        //假設這里是一個很費時間的一個操作
        return 0;
    });

    std::cout << "Main Thread ID:" << std::this_thread::get_id() << std::endl;

    //如果當前任務未完成的話诫隅,主線程會堵塞腐魂,當然我們也可以把堵塞的任務傳遞給其他線程做
    std::cout << "Ret:" << ret.get() << std::endl;

    return  0;
}

* 范例2

多線程下的使用

#include <iostream>
#include <future>

//任務方法
void task(std::promise<int> &prom)
{
    int ret;
    //假設這里是一個很費時間的一個操作
    ret = 4;

    prom.set_value_at_thread_exit(ret);
}

//打印任務結果
void printRet(std::future<int> &future)
{
    std::cout << "ret:" << future.get() << std::endl;
}

int main(int argc, char* args[])
{
    std::promise<int> prom;
    std::future<int> future = prom.get_future();

    //創(chuàng)建線程執(zhí)行任務
    std::thread t = std::thread(task, std::ref(prom));
    //創(chuàng)建線程接受任務執(zhí)行結果
    std::thread t2 = std::thread(printRet, std::ref(future));

    //等待線程完成
    t.join();
    t2.join();

    return  0;
}

* 范例3

參數傳遞

#include <iostream>
#include <future>

int sum(int a, int b)
{
    return  a + b;
}

int main(int argc, char* args[])
{

    //創(chuàng)建完成后線程實際上已經開始運行,參數附加在末尾
    std::future<int> ret = std::async(sum, 1, 2);

    std::cout << "Main Thread ID:" << std::this_thread::get_id() << std::endl;

    //如果當前任務未完成的話逐纬,主線程會堵塞蛔屹,當然我們也可以把堵塞的任務傳遞給其他線程做
    std::cout << "Ret:" << ret.get() << std::endl;

    return  0;
}

std::shared_future

使用與futrue相似。豁生,shared_futrue類型允許使用第二次判导, 并且使用獲得結果與第一次一樣嫉父,如果有一場,拋出的異常也是一樣的
std::shared_futrue f = std::async(task).share();

std::packaged_task(重點)

將任務打包眼刃, 好處是绕辖,可以手動觸發(fā)何時執(zhí)行任務

#include <iostream>
#include <future>

int sum(int a, int b)
{
    std::cout << "Task Thread ID:" << std::this_thread::get_id() << std::endl;
    return  a + b;
}

int main(int argc, char* args[])
{
    //對任務進行封裝
    std::packaged_task<int(int, int)> task(sum);
    //獲取future
    std::future<int> future = task.get_future();

    //直接出發(fā)任務task(1, 2),但是任務處于調用線程中
    //移動到線程中執(zhí)行異步任務
    std::thread t = std::thread(std::move(task), 1, 3);

    std::cout << "Main Thread ID:" << std::this_thread::get_id() << std::endl;

    std::cout << "Ret:" << future.get() << std::endl;
    t.join();
    return 0;
}

范例 4

使用wait_for 等待任務完成

#include <iostream>
#include <future>

double recursive(double a)
{
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
    if ( a == 0)
    {
        return a;
    }

    return  recursive(a - 1) + a;
}

int main()
{
    std::packaged_task<double(double)> task(recursive);
    std::future<double> future = task.get_future();


    //移動到線程中處理
    std::thread t = std::thread(std::move(task), 1000);
    std::thread t2 = std::thread([](std::future<double>& future){
        //等待線程完成執(zhí)行
        while (future.wait_for(std::chrono::milliseconds(200)) == std::future_status::timeout)
        {
            std::cout << ".";
        }
        std::cout << "\n" << std::endl;

        std::cout << "result:" << future.get() << std::endl;
    }, std::ref(future));

    t.join();
    t2.join();

    return 0;
}

范例 5

futrue共享狀態(tài)在get調用后就解除,下次調用會發(fā)生報錯擂红。 但是使用shared_future的時候仪际,get方法可調用多次,但是結果是一樣的

#include <iostream>
#include <future>

int do_work()
{
    return 100;
}

int main()
{
    std::future<int> future = std::async(do_work);
    //獲取共享future
    std::shared_future<int> shared_future = future.share();

    //shared_future多次獲取結果
    std::cout << "ret1:" << shared_future.get() << std::endl;
    std::cout << "ret2:" << shared_future.get() << std::endl;
    return 0;
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末昵骤,一起剝皮案震驚了整個濱河市树碱,隨后出現的幾起案子,更是在濱河造成了極大的恐慌变秦,老刑警劉巖成榜,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異蹦玫,居然都是意外死亡赎婚,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進店門樱溉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來挣输,“玉大人,你說我怎么就攤上這事福贞×媒溃” “怎么了?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵挖帘,是天一觀的道長完丽。 經常有香客問我,道長拇舀,這世上最難降的妖魔是什么舰涌? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮你稚,結果婚禮上瓷耙,老公的妹妹穿的比我還像新娘。我一直安慰自己刁赖,他們只是感情好搁痛,可當我...
    茶點故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著宇弛,像睡著了一般鸡典。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上枪芒,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天彻况,我揣著相機與錄音谁尸,去河邊找鬼。 笑死纽甘,一個胖子當著我的面吹牛良蛮,可吹牛的內容都是我干的。 我是一名探鬼主播悍赢,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼决瞳,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了左权?” 一聲冷哼從身側響起皮胡,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎赏迟,沒想到半個月后屡贺,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡锌杀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年甩栈,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片抛丽。...
    茶點故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖饰豺,靈堂內的尸體忽然破棺而出亿鲜,到底是詐尸還是另有隱情,我是刑警寧澤冤吨,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布蒿柳,位于F島的核電站,受9級特大地震影響漩蟆,放射性物質發(fā)生泄漏垒探。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一怠李、第九天 我趴在偏房一處隱蔽的房頂上張望圾叼。 院中可真熱鬧,春花似錦捺癞、人聲如沸夷蚊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽惕鼓。三九已至,卻和暖如春唐础,著一層夾襖步出監(jiān)牢的瞬間箱歧,已是汗流浹背矾飞。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留呀邢,地道東北人洒沦。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像驼鹅,于是被迫代替她去往敵國和親微谓。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,685評論 2 360