本部落格參考自https://thispointer.com/c11-tutorial/
C++多線程的在某些場景需要實作異步操作,由std::futer 和std::asych, std::packaged_task, std::promise搭配使用。
目錄
1.std::future
2.std::promise
3.std::asych
4.std::packaged_task
1.std::future
std::future是一個類模闆,它的模闆類可通路“未來”的值,進而實作異步通路。
建立文法:
與std::futer 和std::asych, std::packaged_task, std::promise搭配使用對應的建立文法如下
std::future<int> futureObj = promiseObj.get_future();
std::future<std::string> resultFromDB = std::async(std::launch::async, fetchDataFromDB, "Data");
std::future<std::string> result = task.get_future();
調用文法:
擷取future結果有三種方式:get、wait、wait_for,其中get等待異步操作結束并傳回結果,wait隻是等待異步操作完成,沒有傳回值,wait_for是逾時等待傳回結果(參考自https://blog.csdn.net/daaikuaichuan/article/details/81173303)
std::cout<<futureObj.get()<<std::endl; //在get到值之前程式會一直等待
2.std::promise
建立文法:
std::promise<int> promiseObj;
調用文法:
promObj->set_value(35);
完整代碼:
#include <iostream>
#include <thread>
#include <future>
void initiazer(std::promise<int> * promObj)
{
std::cout<<"Inside Thread"<<std::endl;
promObj->set_value(35);
}
int main()
{
std::promise<int> promiseObj;
std::future<int> futureObj = promiseObj.get_future();
std::thread th(initiazer, &promiseObj);
std::cout<<futureObj.get()<<std::endl;
th.join();
return 0;
}
3.std::asych
建立文法:
std::asych直接在建立時就與future變量關聯,并且建立對應的線程。與普通的多線程不同的是它可以通過future得到該線程函數的結果。
std::future<std::string> resultFromDB = std::async(std::launch::async, fetchDataFromDB, "Data");
完整代碼:
#include <iostream>
#include <string>
#include <chrono>
#include <thread>
#include <future>
using namespace std::chrono;
std::string fetchDataFromDB(std::string recvdData)
{
// Make sure that function takes 5 seconds to complete
std::this_thread::sleep_for(seconds(5));
//Do stuff like creating DB Connection and fetching Data
return "DB_" + recvdData;
}
std::string fetchDataFromFile(std::string recvdData)
{
// Make sure that function takes 5 seconds to complete
std::this_thread::sleep_for(seconds(5));
//Do stuff like fetching Data File
return "File_" + recvdData;
}
int main()
{
// Get Start Time
system_clock::time_point start = system_clock::now();
std::future<std::string> resultFromDB = std::async(std::launch::async, fetchDataFromDB, "Data");
//Fetch Data from File
std::string fileData = fetchDataFromFile("Data");
//Fetch Data from DB
// Will block till data is available in future<std::string> object.
std::string dbData = resultFromDB.get();
// Get End Time
auto end = system_clock::now();
auto diff = duration_cast < std::chrono::seconds > (end - start).count();
std::cout << "Total Time Taken = " << diff << " Seconds" << std::endl;
//Combine The Data
std::string data = dbData + " :: " + fileData;
//Printing the combined Data
std::cout << "Data = " << data << std::endl;
return 0;
}
4.std::packaged_task
建立文法:
輸入模闆是函數原型std::packaged_task<std::string (std::string)> task(getDataFromDB);初始化輸入的是函數getDataFromDB
std::packaged_task<std::string (std::string)> task(getDataFromDB);
調用文法:
這時packaged_task對象就相當于普通的回調函數,傳入thread對象實作多線程,與普通的多線程不同的是它可以通過future得到該線程函數的結果。
// Fetch the associated future<> from packaged_task<>
std::future<std::string> result = task.get_future();
// Pass the packaged_task to thread to run asynchronously
std::thread th(std::move(task), "Arg");
完整代碼:
#include <iostream>
#include <thread>
#include <future>
#include <string>
// Fetch some data from DB
std::string getDataFromDB( std::string token)
{
// Do some stuff to fetch the data
std::string data = "Data fetched from DB by Filter :: " + token;
return data;
}
int main()
{
// Create a packaged_task<> that encapsulated the callback i.e. a function
std::packaged_task<std::string (std::string)> task(getDataFromDB);
// Fetch the associated future<> from packaged_task<>
std::future<std::string> result = task.get_future();
// Pass the packaged_task to thread to run asynchronously
std::thread th(std::move(task), "Arg");
// Join the thread. Its blocking and returns when thread is finished.
th.join();
// Fetch the result of packaged_task<> i.e. value returned by getDataFromDB()
std::string data = result.get();
std::cout << data << std::endl;
return 0;
}