若是咱們想要異步獲取線程處理結果,可使用future與async。async返回一個future對象,等待線程能夠在future對象上獲取異步線程的處理值。這裏的異步,實際上主線程會阻塞。ios
【一】future的狀態異步
future有三種狀態:async
std::future_status::deferred; //表示異步線程還未啓動 std::future_status::ready; //表示異步線程已經執行完畢,並已經將執行結果寫入到future中 std::future_status::timeout; // 表示異步線程處理超時,並無將結果寫入future中
【二】async是否啓動線程函數
async是否啓動異步線程,有async第一個參數決定,async接口定義以下:this
async(std::launch::async | std::launch::deferred, f, args...)
第一個參數表示異步線程啓動的方式,有以下兩種方式:spa
std::launch::async; // 表示表用async函數後,當即啓動異步線程 std::launch::deferred; // 表示線程延遲啓動,當調用future.get或者future.wait時,纔會建立異步線程並啓動
而async的默認方式見接口所示:線程
std::launch::async | std::launch::deferred // 表示是否啓動線程由系統負載決定,若是系統負載太重,則可能不啓動異步線程計算,則此時future的狀態不會爲ready, 通常狀況下,這種默認設置夠用了,可是若是須要必定以異步線程的方式執行,則顯示修改啓動方式爲async
【三】future的四個方法code
future<int> fu; fu.get();
get聲明以下:對象
返回future中存取的int值,get在拿到數據以前,會一直阻塞接口
fu.wait();
wait聲明以下:
沒有返回值,一直等待,直到future狀態爲ready爲止
fu.wait_for();
wait_for聲明以下:
等待必定的時間,返回值爲future的狀態,若是等待超時,返回time_out
fu.wait_until();就是等待到某個時間點,與wait_for相似。
【四】async採用默認啓動參數
#include<iostream> #include<thread> #include<mutex> #include<condition_variable> #include<future> #include<chrono> using namespace std; int f(int i) { cout << "start" << endl; cout << "this thread id = " << std::this_thread::get_id() << endl; std::this_thread::sleep_for(2s); cout << "end" << endl; return i; } int main(int argc, int * argv[]) { future<int> fu = std::async(f, 8); cout << fu.get() << endl; cout << "main thread id = " << std::this_thread::get_id() << endl; cout << "main" << endl; system("pause"); }
結果以下:
能夠看出,這裏線程id不同。
【五】先wait,後get
#include<iostream> #include<thread> #include<mutex> #include<condition_variable> #include<future> #include<chrono> using namespace std; int f(int i) { cout << "start" << endl; cout << "this thread id = " << std::this_thread::get_id() << endl; std::this_thread::sleep_for(2s); cout << "end" << endl; return i; } int main(int argc, int * argv[]) { future<int> fu = std::async(f, 8); fu.wait(); cout << fu.get() << endl; cout << "main thread id = " << std::this_thread::get_id() << endl; cout << "main" << endl; system("pause"); }
結果以下:
【六】等待超時
#include<iostream> #include<thread> #include<mutex> #include<condition_variable> #include<future> #include<chrono> using namespace std; int f(int i) { cout << "start" << endl; cout << "this thread id = " << std::this_thread::get_id() << endl; std::this_thread::sleep_for(2s); cout << "end" << endl; return i; } int main(int argc, int * argv[]) { future<int> fu = std::async(f, 8); if (fu.wait_for(1s) == std::future_status::timeout) { cout << "time out" << endl; } else { cout << fu.get() << endl; } cout << "main thread id = " << std::this_thread::get_id() << endl; cout << "main" << endl; system("pause"); }
結果以下:
若是超時了還get,則會繼續等待,直到future狀態爲ready,而後取出數據
#include<iostream> #include<thread> #include<mutex> #include<condition_variable> #include<future> #include<chrono> using namespace std; int f(int i) { cout << "start" << endl; cout << "this thread id = " << std::this_thread::get_id() << endl; std::this_thread::sleep_for(2s); cout << "end" << endl; return i; } int main(int argc, int * argv[]) { future<int> fu = std::async(f, 8); if (fu.wait_for(1s) == std::future_status::timeout) { cout << "time out" << endl; } // 超時繼續get cout << fu.get() << endl; cout << "main thread id = " << std::this_thread::get_id() << endl; cout << "main" << endl; system("pause"); }
結果以下:
【七】設置aysnc啓動方式
#include<iostream> #include<thread> #include<mutex> #include<condition_variable> #include<future> #include<chrono> using namespace std; int f(int i) { cout << "start" << endl; cout << "this thread id = " << std::this_thread::get_id() << endl; std::this_thread::sleep_for(2s); cout << "end" << endl; return i; } int main(int argc, int * argv[]) { // 設置啓動方式爲async future<int> fu = std::async(std::launch::async,f, 8); if (fu.wait_for(1s) == std::future_status::timeout) { cout << "time out" << endl; } cout << fu.get() << endl; cout << "main thread id = " << std::this_thread::get_id() << endl; cout << "main" << endl; system("pause"); }
結果以下: