用C++11的std::async代替线程的创建
轉(zhuǎn)自:http://www.cnblogs.com/qicosmos/p/3534211.html
c++11中增加了線程,使得我們可以非常方便的創(chuàng)建線程,它的基本用法是這樣的:
void f(int n); std::thread t(f, n + 1); t.join();但是線程畢竟是屬于比較低層次的東西,有時候使用有些不便,比如我希望獲取線程函數(shù)的返回結(jié)果的時候,我就不能直接通過thread.join()得到結(jié)果,這時就必須定義一個變量,在線程函數(shù)中去給這個變量賦值,然后join,最后得到結(jié)果,這個過程是比較繁瑣的。c++11還提供了異步接口std::async,通過這個異步接口可以很方便的獲取線程函數(shù)的執(zhí)行結(jié)果。std::async會自動創(chuàng)建一個線程去調(diào)用線程函數(shù),它返回一個std::future,這個future中存儲了線程函數(shù)返回的結(jié)果,當(dāng)我們需要線程函數(shù)的結(jié)果時,直接從future中獲取,非常方便。但是我想說的是,其實std::async給我們提供的便利可不僅僅是這一點,它首先解耦了線程的創(chuàng)建和執(zhí)行,使得我們可以在需要的時候獲取異步操作的結(jié)果;其次它還提供了線程的創(chuàng)建策略(比如可以通過延遲加載的方式去創(chuàng)建線程),使得我們可以以多種方式去創(chuàng)建線程。在介紹async具體用法以及為什么要用std::async代替線程的創(chuàng)建之前,我想先說一說std::future、std::promise和std::packaged_task。
std::future
std::future是一個非常有用也很有意思的東西,簡單說std::future提供了一種訪問異步操作結(jié)果的機(jī)制。從字面意思來理解,它表示未來,我覺得這個名字非常貼切,因為一個異步操作我們是不可能馬上就獲取操作結(jié)果的,只能在未來某個時候獲取,但是我們可以以同步等待的方式來獲取結(jié)果,可以通過查詢future的狀態(tài)(future_status)來獲取異步操作的結(jié)果。future_status有三種狀態(tài):
- deferred:異步操作還沒開始
- ready:異步操作已經(jīng)完成
- timeout:異步操作超時
獲取future結(jié)果有三種方式:get、wait、wait_for,其中g(shù)et等待異步操作結(jié)束并返回結(jié)果,wait只是等待異步操作完成,沒有返回值,wait_for是超時等待返回結(jié)果。
std::promise
std::promise為獲取線程函數(shù)中的某個值提供便利,在線程函數(shù)中給外面?zhèn)鬟M(jìn)來的promise賦值,當(dāng)線程函數(shù)執(zhí)行完成之后就可以通過promis獲取該值了,值得注意的是取值是間接的通過promise內(nèi)部提供的future來獲取的。它的基本用法:
std::promise<int> pr;std::thread t([](std::promise<int>& p){ p.set_value_at_thread_exit(9); },std::ref(pr));std::future<int> f = pr.get_future();auto r = f.get();std::packaged_task
std::packaged_task它包裝了一個可調(diào)用的目標(biāo)(如function, lambda expression, bind expression, or another?function object),以便異步調(diào)用,它和promise在某種程度上有點像,promise保存了一個共享狀態(tài)的值,而packaged_task保存的是一個函數(shù)。它的基本用法:
std::packaged_task<int()> task([](){ return 7; });std::thread t1(std::ref(task)); std::future<int> f1 = task.get_future(); auto r1 = f1.get();std::promise、std::packaged_task和std::future的關(guān)系
至此, 我們介紹了std::async相關(guān)的幾個對象std::future、std::promise和std::packaged_task,其中std::promise和std::packaged_task的結(jié)果最終都是通過其內(nèi)部的future返回出來的,不知道讀者有沒有搞糊涂,為什么有這么多東西出來,他們之間的關(guān)系到底是怎樣的?且聽我慢慢道來,std::future提供了一個訪問異步操作結(jié)果的機(jī)制,它和線程是一個級別的屬于低層次的對象,在它之上高一層的是std::packaged_task和std::promise,他們內(nèi)部都有future以便訪問異步操作結(jié)果,std::packaged_task包裝的是一個異步操作,而std::promise包裝的是一個值,都是為了方便異步操作的,因為有時我需要獲取線程中的某個值,這時就用std::promise,而有時我需要獲一個異步操作的返回值,這時就用std::packaged_task。那std::promise和std::packaged_task之間又是什么關(guān)系呢?說他們沒關(guān)系也關(guān)系,說他們有關(guān)系也有關(guān)系,都取決于你了,因為我可以將一個異步操作的結(jié)果保存到std::promise中。如果讀者還沒搞清楚他們的關(guān)系的話,我就用更通俗的話來解釋一下。比如,一個小伙子給一個姑娘表白真心的時候也許會說:”我許諾會給你一個美好的未來“或者”我會努力奮斗為你創(chuàng)造一個美好的未來“。姑娘往往會說:”我等著“。現(xiàn)在我來將這三句話用c++11來翻譯一下:
小伙子說:我許諾會給你一個美好的未來等于c++11中"std::promise a std::future";?
小伙子說:我會努力奮斗為你創(chuàng)造一個美好的未來等于c++11中"std::packaged_task a future";?
姑娘說:我等著等于c++11中"future.get()/wait()";
小伙子兩句話的個中差異,自己琢磨一下,這點差異也是std::promise和std::packaged_task的差異?,F(xiàn)實中的山盟海誓靠不靠得住我不知道,但是c++11中的許諾和未來是一定可靠的,發(fā)起來了許諾就一定有未來。細(xì)想起來c++11標(biāo)準(zhǔn)的制定者選定的關(guān)鍵字真是貼切而有意思!好了,插科打諢到此了,現(xiàn)在言歸正傳,回過頭來說說std::async。
為什么要用std::async代替線程的創(chuàng)建
std::async又是干啥的,已經(jīng)有了td::future、std::promise和std::packaged_task,夠多的了,真的還要一個std::async來湊熱鬧嗎,std::async表示很委屈:我不是來湊熱鬧的,我是來幫忙的。是的,std::async是為了讓用戶的少費(fèi)點腦子的,它讓這三個對象默契的工作。大概的工作過程是這樣的:std::async先將異步操作用std::packaged_task包裝起來,然后將異步操作的結(jié)果放到std::promise中,這個過程就是創(chuàng)造未來的過程。外面再通過future.get/wait來獲取這個未來的結(jié)果,怎么樣,std::async真的是來幫忙的吧,你不用再想到底該怎么用std::future、std::promise和std::packaged_task了,std::async已經(jīng)幫你搞定一切了!
現(xiàn)在來看看std::async的原型async(std::launch::async | std::launch::deferred, f, args...),第一個參數(shù)是線程的創(chuàng)建策略,有兩種策略,默認(rèn)的策略是立即創(chuàng)建線程:
- std::launch::async:在調(diào)用async就開始創(chuàng)建線程。
- std::launch::deferred:延遲加載方式創(chuàng)建線程。調(diào)用async時不創(chuàng)建線程,直到調(diào)用了future的get或者wait時才創(chuàng)建線程。
第二個參數(shù)是線程函數(shù),第三個參數(shù)是線程函數(shù)的參數(shù)。
std::async基本用法:
總結(jié):
std::async是更高層次上的異步操作,使我們不用關(guān)注線程創(chuàng)建內(nèi)部細(xì)節(jié),就能方便的獲取異步執(zhí)行狀態(tài)和結(jié)果,還可以指定線程創(chuàng)建策略,應(yīng)該用std::async替代線程的創(chuàng)建,讓它成為我們做異步操作的首選。
?
如果你覺得這篇文章對你有用,可以點一下推薦,謝謝。
c++11 boost技術(shù)交流群:296561497,歡迎大家來交流技術(shù)。
一點夢想:盡自己一份力,讓c++的世界變得更美好!創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎
總結(jié)
以上是生活随笔為你收集整理的用C++11的std::async代替线程的创建的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ros(2) 发布者publisher的
- 下一篇: LPTSTR、LPCSTR、LPCTST