九、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上,來得到綁定的值

std::future 的成員函數

wait_for():主線程等你x秒,希望你返回值。

  std::future_status::timeout:返回超時

  \ std::future_status::ready:准時返回

  \ std::future_status::deferred:線程延遲執行(實際並沒有創建子線程,而是在主線程中執行)

 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() {
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     return 5;
15 }
16  
17  
18 int main() {
19     A a;
20     int tmp = 12;
21     cout << "main" << "threadid = " << std::this_thread::get_id() << endl;
22     std::future<int> result = std::async(mythread);
23     cout << "continue........" << endl;
24     //cout << result1.get() << endl; //卡在這里等待mythread()執行完畢,拿到結果
25     std::future_status status = result.wait_for(std::chrono::seconds(1));
26     if (status == std::future_status::timeout) {
27         //超時:表示線程還沒有執行完
28         cout << "超時了,線程還沒有執行完" << endl;
29     }
30     //類成員函數
31     return 0;
32 }

std::shared_future:也是個類模板

std::future的 get() 成員函數是轉移數據(移動語義),只能調用一次

  auto res=tmp.get();將相當於tmp中的返回值移動到res中了,tmp的返回值為空了。

std::shared_future 的 get() 函數是賦值數據

  如果我多個線程都想要get()的返回值怎么辦呢?就是這個了

 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() {
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     return 5;
15 }
16  
17 int mythread2(std::shared_future<int> &res) {
18     cout << "mythread2() start" << "threadid = " << std::this_thread::get_id() << endl;
19     auto myresult3 = res.get();
20     cout << "mythread2() end" << "threadid = " << std::this_thread::get_id() << endl;
21     return 5;
22 }
23  
24 int main() {
25     int tmp = 12;
26     cout << "main" << "threadid = " << std::this_thread::get_id() << endl;
27     std::packaged_task<int()> mypt(mythread);
28     std::thread t1(std::ref(mypt));
29     std::future<int> result = mypt.get_future();
30     //std::shared_future<int> result_s(std::move(result));
31     bool ifcanget = result.valid(); //判斷future 中的值是不是一個有效值
32     std::shared_future<int> result_s(result.share()); //執行完畢后result_s里有值,而result里空了
33     t1.join();
34     
35     auto myresult1 = result_s.get();
36     auto myresult2 = result_s.get();
37  
38     std::thread t2(std::ref(mythread2), std::ref(result_s));
39     t2.join();
40     cout << "good luck" << endl;
41     return 0;
42 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM