還是接著講多線程,照例,可以先看上一篇文章。
我們再次回顧一下上次編寫的使用async的多線程程序:
int main()
{async([]{ cout << "Maybe a new thread?" << endl; });cout << "Yeah, u r right!" << endl;return 0;
}
從輸出的打印可知,編譯器提醒我們不要忽略函數的返回值(即使,這個函數的返回值是 void
)
AsyncTest.cpp: In function 'int main()':
AsyncTest.cpp:9:54: warning: ignoring return value of 'std::future<typename std::__invoke_result<typename std::decay<_Tp>::type, typename std::decay<_Args>::type ...>::type> std::async(_Fn&&, _Args&& ...) [with _Fn = main()::<lambda()>; _Args = {}; typename __invoke_result<typename decay<_Tp>::type, typename decay<_Args>::type ...>::type = void; typename decay<_Tp>::type = main()::<lambda()>]', declared with attribute 'nodiscard' [-Wunused-result]9 | { cout << "Maybe a new thread?" << endl; });| ^
In file included from AsyncTest.cpp:2:
C:/tools/mingw-w64-gcc-13.2-stable-r40/include/c++/13.2.0/future:1828:5: note: declared here1828 | async(_Fn&& __fn, _Args&&... __args)| ^~~~~
Maybe a new thread?
Yeah, u r right!
async
相比thread
的一個優勢就是,可以獲取線程內函數的返回值,而這個返回值,使用std::future
獲取。
std::future
前面提到過,async
是否新開一個線程執行函數,取決于傳入的枚舉值。當傳入deferred
的時候,async
會延遲到get
再執行線程內的函數,實際上就是單線程。而這里的get
就是獲取函數返回值的方式。我們改造下上面的代碼:
future<int> returnVal = async([] -> int{ cout << "Maybe a new thread?" << endl; return 0; });cout << "Yeah, u r right! val = " << returnVal.get() << endl;
編譯器通過future
構造時傳入的參數類型認定函數的返回值,并調用get
獲取。
future可以調用wait()阻塞主線程等待子線程結束(類似于thread的join()),事實上,當函數返回值為void的時候,調用get
也能起到同樣的效果;也可以調用wait_for
,這可以讓主線程阻塞一段時間。其參數為C++新引入的chrono::duration
,講清這個概念估計還得單獨開一篇文章(我感覺還不如sleep
好用,可能我工作接觸的都是小項目吧)
這里先寫幾個常見的duration
:
typedef duration<long long, nano> nanoseconds; // 納秒
typedef duration<long long, micro> microseconds; // 微秒
typedef duration<long long, milli> milliseconds; // 毫秒
typedef duration<long long> seconds; // 秒
typedef duration<int, ratio<60> > minutes; // 分鐘
typedef duration<int, ratio<3600> > hours; // 小時
返回值如下:
返回值 | 含義 |
---|---|
future_status::ready | 阻塞時間內,線程結束 |
future_status::timeout | 阻塞時間內,線程未結束 |
future_status::deferred | 線程以非異步方式(deferred)啟動,不會阻塞,返回此值 |
示例代碼如下:
future<int> returnVal = async([] -> int{ cout << "Maybe a new thread?" << endl; return 0; });returnVal.wait_for(chrono::seconds(10));cout << "Yeah, u r right! val = " << returnVal.get() << endl;return 0;