1. 程式人生 > 其它 >九、std::async非同步執行緒

九、std::async非同步執行緒

std::async、std::future建立後臺任務並返回值

std::async是一個函式模板,用來啟動一個非同步任務,啟動起來一個非同步任務之後,它返回一個std::future物件,這個物件是個類模板。

非同步任務:就是自動建立一個執行緒,並開始 執行對應的執行緒入口函式,它返回一個std::future物件,這個std::future物件中就含有執行緒入口函式所返回的結果,我們可以通過呼叫future物件的成員函式get()來獲取結果。

“future”將來的意思,也有人稱呼std::future提供了一種訪問非同步操作結果的機制,就是說這個結果你可能沒辦法馬上拿到,但是在不久的將來,這個執行緒執行完畢的時候,你就能夠拿到結果了,所以,大家這麼理解:future中儲存著一個值,這個值是在將來的某個時刻能夠拿到。

std::future物件的get()成員函式會等待執行緒執行結束並返回結果,拿不到結果它就會一直等待,有點像join(),但它可以獲取結果。

 1 #include <thread>
 2 #include <iostream>
 3 #include <list>
 4 #include <map>
 5 #include <mutex>
 6 #include <future>
 7 using namespace std;
 8 class A {
 9 public:
10     int mythread(int
mypar) { 11 cout << mypar << endl; 12 return mypar; 13 } 14 }; 15 16 17 int mythread() { 18 cout << "mythread() start" << "threadid = " << std::this_thread::get_id() << endl; 19 std::chrono::milliseconds dura(5000); 20 std::this_thread::sleep_for(dura);
21 cout << "mythread() end" << "threadid = " << std::this_thread::get_id() << endl; 22 return 5; 23 } 24 25 26 int main() { 27 A a; 28 int tmp = 12; 29 cout << "main" << "threadid = " << std::this_thread::get_id() << endl; 30 std::future<int> result1 = std::async(mythread); 31 cout << "主子並行........" << endl; 32 cout << result1.get() << endl; //卡在這裡等待mythread()執行完畢,拿到結果,只能呼叫一次 33 34 //類成員函式 35 std::future<int> result2 = std::async(&A::mythread, &a, tmp); //引數是物件引用才能保證執行緒裡執行的是同一個物件 36 cout << result2.get() << endl; 37 cout << "good luck" << endl; 38 return 0; 39 }

通過向std::async()傳遞一個引數,改引數是std::launch型別(列舉型別),來達到一些特殊的目的:

1、std::lunch::deferred:

  表示執行緒入口函式呼叫被延遲到,std::future的wait()或者get()函式呼叫時才執行;

  如果wait()或者get()沒有被呼叫,則不會執行。實際上根本就沒有建立。(實際上延遲呼叫,並沒有建立新執行緒,是在主執行緒中呼叫的執行緒入口函式)。

2、std::launch::async

  在呼叫async函式的時候就開始建立執行緒。async()這個函式預設用的就是std::launch::async標記。

std::packaged_task:打包任務,把任務包裝起來。

類模板,它的模板引數是各種課呼叫物件,通過packaged_task把各種可呼叫物件包裝起來,方便將來作為執行緒入口函式。(算了,不是很懂!)

 1 #include <thread>
 2 #include <iostream>
 3 #include <list>
 4 #include <map>
 5 #include <mutex>
 6 #include <future>
 7 using namespace std;
 8  
 9 int mythread(int mypar) {
10     cout << mypar << endl;
11     cout << "mythread() start" << "threadid = " << std::this_thread::get_id() << endl;
12     std::chrono::milliseconds dura(5000);
13     std::this_thread::sleep_for(dura);
14     cout << "mythread() end" << "threadid = " << std::this_thread::get_id() << endl;
15     return 5;
16 }
17  
18  
19 int main() {
20     int tmp = 12;
21     cout << "main" << "threadid = " << std::this_thread::get_id() << endl;
22     std::packaged_task<int(int)> mypt(mythread); //我們把函式mythread通過packaged_task包裝起來
23     std::thread t1(std::ref(mypt), 1);
24     t1.join();
25     std::future<int> result = mypt.get_future(); 
26     //std::future物件裡包含有執行緒入口函式的返回結果,這裡result儲存mythread返回的結果。
27     cout << result.get() << endl;
28     cout << "good luck" << endl;
29     return 0;
30 }

std::promise,類模板

我們能夠在某個執行緒中給它賦值,然後我們可以在其他執行緒中,把這個值取出來

 1 #include <thread>
 2 #include <iostream>
 3 #include <list>
 4 #include <map>
 5 #include <mutex>
 6 #include <future>
 7 using namespace std;
 8  
 9 void mythread(std::promise<int> &tmp, int clac) {
10     cout << "mythread() start" << "threadid = " << std::this_thread::get_id() << endl;
11     std::chrono::milliseconds dura(5000);   
12     std::this_thread::sleep_for(dura);
13     cout << "mythread() end" << "threadid = " << std::this_thread::get_id() << endl;
14     int result = clac;
15     tmp.set_value(result); //結果儲存到了tmp這個物件中
16     return;
17 }
18  
19 vector<std::packaged_task<int(int)>> task_vec;
20  
21 int main() {
22     std::promise<int> myprom;
23     std::thread t1(mythread, std::ref(myprom), 180);
24     t1.join(); //在這裡執行緒已經執行完了
25     std::future<int> fu1 = myprom.get_future(); //promise和future繫結,用於獲取執行緒返回值
26     auto result = fu1.get();
27     cout << "result = " << result << endl;
28 }

總結:通過promise儲存一個值,在將來某個時刻我們通過吧一個future繫結到這個promise上,來得到繫結的值

心之所願,永不相忘