本博客參考自https://thispointer.com/c11-tutorial/
C++多線程的在某些場景需要實現異步操作,由std::futer 和std::asych, std::packaged_task, std::promise搭配使用。
目錄
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;
}