欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++11中多線程編程-std::async的深入講解

 更新時(shí)間:2020年11月02日 11:00:27   作者:MSBETA  
這篇文章主要給大家介紹了關(guān)于C++11中多線程編程-std::async的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

前言

C++11中提供了異步線程接口std::async,std::async是異步編程的高級封裝,相對于直接使用std::thread,std::async的優(yōu)勢在于:

1、std::async會自動創(chuàng)建線程去調(diào)用線程函數(shù),相對于低層次的std::thread,使用起來非常方便;

2、std::async返回std::future對象,通過返回的std::future對象我們可以非常方便的獲取到線程函數(shù)的返回結(jié)果;

3、std::async提供了線程的創(chuàng)建策略,可以指定同步或者異步的方式去創(chuàng)建線程;

1、函數(shù)原型

C++ 11中提供如下函數(shù)原型:

template< class Function, class... Args>
std::future<std::result_of_t<std::decay_t<Function>(std::decay_t<Args>...)>>
 async( Function&& f, Args&&... args );
template< class Function, class... Args >
std::future<std::result_of_t<std::decay_t<Function>(std::decay_t<Args>...)>>
 async( std::launch policy, Function&& f, Args&&... args );

其中,參數(shù)f接收一個(gè)可調(diào)用對象(仿函數(shù)、lambda表達(dá)式、類成員函數(shù)、普通函數(shù)……),用于異步或是同步執(zhí)行。

參數(shù)policy用于指定同步執(zhí)行或者異步執(zhí)行可調(diào)用對象,它的可選值有三種:

1)std::launch::async:異步執(zhí)行可調(diào)用對象;

2)std::launch::deferred:同步執(zhí)行可調(diào)用對象;

3)std::launch::async | std::launch::deferred 可以異步或是同步,取決于具體實(shí)現(xiàn)。

函數(shù)返回值:

函數(shù)返回值是std::future對象,我們可以執(zhí)行g(shù)et、wait、wait_for、wait_until函數(shù)獲取或者等待執(zhí)行結(jié)果。

調(diào)用std::future對象的get函數(shù)時(shí),如果執(zhí)行的是異步執(zhí)行策略,如果異步執(zhí)行沒有結(jié)束,get函數(shù)調(diào)用會阻塞當(dāng)前當(dāng)前調(diào)用線程;如果執(zhí)行的是同步執(zhí)行策略,只有當(dāng)調(diào)用get函數(shù)時(shí)才真正執(zhí)行。

調(diào)用std::future對象的wait*函數(shù)時(shí),可能返回三種狀態(tài):

1)std::future_status::deferred:可調(diào)用對象尚未開始執(zhí)行;

2)std::future_status::ready:可調(diào)用對象執(zhí)行完畢;

3)std::future_status::timeout:可調(diào)用對象執(zhí)行超時(shí);

2、頭文件

#include <future>

3、同步或異步讀取文件內(nèi)容

我們模擬異步從數(shù)據(jù)庫中讀取數(shù)據(jù)和同步方式從文件中讀取數(shù)據(jù),從其中可以看到std::async的使用方法。

#include <iostream>
#include <string>
#include <chrono>
#include <thread>
#include <future>
 
using namespace std::chrono;
 
std::string fetchDataFromDB(std::string recvData) {
 std::cout << "fetchDataFromDB start" << std::this_thread::get_id() << std::endl;
 std::this_thread::sleep_for(seconds(5));
 return "DB_" + recvData;
}
 
std::string fetchDataFromFile(std::string recvData) {
 std::cout << "fetchDataFromFile start" << std::this_thread::get_id() << std::endl;
 std::this_thread::sleep_for(seconds(3));
 return "File_" + recvData;
}
 
int main() {
 std::cout << "main start" << std::this_thread::get_id() << std::endl;
 
 //獲取開始時(shí)間
 system_clock::time_point start = system_clock::now();
 
 std::future<std::string> resultFromDB = std::async(std::launch::async, fetchDataFromDB, "Data");
 
 //從文件獲取數(shù)據(jù)
 std::future<std::string> fileData = std::async(std::launch::deferred, fetchDataFromFile, "Data");
 
 //調(diào)用get函數(shù)fetchDataFromFile才開始執(zhí)行
 std::string FileData = fileData.get();
 //如果fetchDataFromDB執(zhí)行沒有完成,get會一直阻塞當(dāng)前線程
 std::string dbData = resultFromDB.get();
 
 //獲取結(jié)束時(shí)間
 auto end = system_clock::now();
 
 auto diff = duration_cast<std::chrono::seconds>(end - start).count();
 std::cout << "Total Time taken= " << diff << "Seconds" << std::endl;
 
 //組裝數(shù)據(jù)
 std::string data = dbData + " :: " + FileData;
 
 //輸出組裝的數(shù)據(jù)
 std::cout << "Data = " << data << std::endl;
 
 return 0;
}

代碼輸出:

main start140677737994048
fetchDataFromFile start140677737994048
fetchDataFromDB start140677720131328
Total Time taken= 5Seconds
Data = DB_Data :: File_Data

4、設(shè)置異步數(shù)據(jù)讀取超時(shí)機(jī)制

有時(shí)我們不能無限制的等待異步任務(wù)執(zhí)行,可以設(shè)置超時(shí)等待時(shí)間(timeout),當(dāng)超時(shí)時(shí)間到達(dá)時(shí),可以選擇放棄等待異步任務(wù)。

如果代碼中,我們設(shè)置了1s的超時(shí)設(shè)置,用于檢查異步線程是否執(zhí)行完畢。

#include <iostream>
#include <string>
#include <chrono>
#include <thread>
#include <future>
 
using namespace std::chrono;
 
std::string fetchDataFromDB(std::string recvData) {
 
 std::cout << "fetchDataFromDB start" << std::this_thread::get_id() << std::endl;
 std::this_thread::sleep_for(seconds(5));
 return "DB_" + recvData;
}
 
 
int main() {
 
 std::cout << "main start" << std::this_thread::get_id() << std::endl;
 
 //獲取開始時(shí)間
 system_clock::time_point start = system_clock::now();
 
 std::future<std::string> resultFromDB = std::async(std::launch::async, fetchDataFromDB, "Data");
 
 std::future_status status;
 std::string dbData;
 do
 {
  status = resultFromDB.wait_for(std::chrono::seconds(1));
 
  switch (status)
  {
  case std::future_status::ready:
   std::cout << "Ready..." << std::endl;
   //獲取結(jié)果
   dbData = resultFromDB.get();
   std::cout << dbData << std::endl;
   break;
  case std::future_status::timeout:
   std::cout << "timeout..." << std::endl;
   break;
  case std::future_status::deferred:
   std::cout << "deferred..." << std::endl;
   break;
  default:
   break;
  }
 
 } while (status != std::future_status::ready);
 
 
 //獲取結(jié)束時(shí)間
 auto end = system_clock::now();
 
 auto diff = duration_cast<std::chrono::seconds>(end - start).count();
 std::cout << "Total Time taken= " << diff << "Seconds" << std::endl;
 
 return 0;
}

程序輸出:

main start140406593357632
fetchDataFromDB start140406575482624
timeout...
timeout...
timeout...
timeout...
Ready...
DB_Data
Total Time taken= 5Seconds

5、使用std::async實(shí)現(xiàn)多線程并發(fā)

既然std::async可以實(shí)現(xiàn)異步調(diào)用,我們很容易就可以借用它實(shí)現(xiàn)多線程并發(fā)。

#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <future>
#include <string>
#include <mutex>
#include <thread>
 
template <typename RandomIt>
int parallel_sum(RandomIt beg, RandomIt end)
{
 std::cout << "thread id:" << std::this_thread::get_id() << std::endl;
 
 auto len = end - beg;
 if (len < 1000)
  return std::accumulate(beg, end, 0);
 
 RandomIt mid = beg + len/2;
 auto handle_me = std::async(std::launch::async,
        parallel_sum<RandomIt>, mid, end);
 auto handle_bm = std::async(std::launch::async,
        parallel_sum<RandomIt>, beg, mid);
 // int sum = parallel_sum(beg, mid);
 return handle_bm.get() + handle_me.get();
}
 
int main()
{
 std::vector<int> v(10000, 1);
 std::cout << "The sum is " << parallel_sum(v.begin(), v.end()) << std::endl;
}

程序輸出如下:

The sum is thread id:140594794530624
thread id:140594776655616
thread id:140594768262912
thread id:140594759870208
thread id:140594672297728
thread id:140594680690432
thread id:140594663905024
thread id:140594655512320
thread id:140594647119616
thread id:140594638726912
thread id:140594269644544
thread id:140594630334208
thread id:140594278037248
thread id:140594252859136
thread id:140594261251840
thread id:140594252859136
thread id:140594236073728
thread id:140594252859136
thread id:140594261251840
thread id:140594630334208
thread id:140594244466432
thread id:140594252859136
thread id:140594227681024
thread id:140594261251840
thread id:140593875384064
thread id:140593850205952
thread id:140593858598656
thread id:140593866991360
thread id:140594647119616
thread id:140594269644544
thread id:140594672297728
10000

6、其它注意事項(xiàng)

在使用時(shí)需要注意,std::future對象的析構(gòu)需要等待std::async執(zhí)行完畢,也就是說,如下面的代碼并不能實(shí)現(xiàn)并發(fā)。原因在于std::async的返回的std::future對象無人接收,是個(gè)臨時(shí)變量,臨時(shí)變量的析構(gòu)會阻塞,直至std::async異步任務(wù)執(zhí)行完成。

std::async(std::launch::async, []{ f(); }); // temporary's dtor waits for f()
std::async(std::launch::async, []{ g(); }); // does not start until f() completes

參考材料

https://en.cppreference.com/w/cpp/thread/async

www.dbjr.com.cn/article/198761.htm

總結(jié)

到此這篇關(guān)于C++11中多線程編程-std::async深入講解的文章就介紹到這了,更多相關(guān)C++11多線程編程-std::async內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++小知識:用++i替代i++

    C++小知識:用++i替代i++

    今天小編就為大家分享一篇關(guān)于C++小知識:用++i替代i++,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • C語言實(shí)現(xiàn)乒乓球比賽

    C語言實(shí)現(xiàn)乒乓球比賽

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)乒乓球比賽,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • C/C++從零開始的cmake教程

    C/C++從零開始的cmake教程

    今天小編就為大家分享一篇關(guān)于C/C++從零開始的cmake教程,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2018-10-10
  • 淺談C++繼承中的名字查找

    淺談C++繼承中的名字查找

    下面小編就為大家?guī)硪黄獪\談C++繼承中的名字查找。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-01-01
  • C語言詳解實(shí)現(xiàn)字符菱形的方法

    C語言詳解實(shí)現(xiàn)字符菱形的方法

    字符菱形是指給定一個(gè)字符,用它構(gòu)造一個(gè)對角線長5個(gè)字符,傾斜放置的菱形。輸入輸入只有一行, 包含一個(gè)字符。輸出該字符構(gòu)成的菱形
    2022-04-04
  • C語言實(shí)現(xiàn)一個(gè)通訊錄

    C語言實(shí)現(xiàn)一個(gè)通訊錄

    這篇文章主要為大家詳細(xì)介紹了用C語言實(shí)現(xiàn)一個(gè)通訊錄,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-02-02
  • C++中的函數(shù)修飾符深入講解

    C++中的函數(shù)修飾符深入講解

    這篇文章主要給大家介紹了關(guān)于C++中函數(shù)修飾符的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-02-02
  • C++ Boost PropertyTree解析INI文件詳解

    C++ Boost PropertyTree解析INI文件詳解

    Boost PropertyTree庫不僅可以解析JSON,XML格式,還可以直接解析INI格式文件。這篇文章就是為大家介紹一下如何通過Boost PropertyTree解析INI文件,需要的可以參考一下
    2022-01-01
  • C++實(shí)現(xiàn)LeetCode(47.全排列之二)

    C++實(shí)現(xiàn)LeetCode(47.全排列之二)

    這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(47.全排列之二),本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • 如何給隨機(jī)數(shù)加密

    如何給隨機(jī)數(shù)加密

    隨機(jī)數(shù)加密的簡單算法,需要的朋友可以參考一下
    2013-03-03

最新評論