国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

C++11并發(fā)與多線程筆記(9) async、future、packaged_task、promise

這篇具有很好參考價值的文章主要介紹了C++11并發(fā)與多線程筆記(9) async、future、packaged_task、promise。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

1、std::async、std::future創(chuàng)建后臺任務(wù)并返回值

std::async: 是一個函數(shù)模板,用來啟動一個異步任務(wù),啟動起來一個異步任務(wù)之后,它返回一個std::future對象,這個對象是個類模板。

什么叫“啟動一個異步任務(wù)”?就是自動創(chuàng)建一個線程,并開始執(zhí)行對應(yīng)的線程入口函數(shù),它返回一個std::future對象,這個std::future對象中就含有線程入口函數(shù)所返回的結(jié)果,我們可以通過調(diào)用future對象的成員函數(shù)get()來獲取結(jié)果。

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

std::future對象的get()成員函數(shù)會等待線程執(zhí)行結(jié)束并返回結(jié)果,拿不到結(jié)果它就會一直等待,感覺有點像join()。但是,它是可以獲取結(jié)果的。

std::future對象的wait()成員函數(shù),用于等待線程返回,本身并不返回結(jié)果,這個效果和 std::thread 的join()更像。

#include <iostream>
#include <future>
using namespace std;
class A {
public:
	int mythread(int mypar) {
		cout << mypar << endl;
		cout << "mythread() start" << "threadid = " << std::this_thread::get_id() << endl;
		std::chrono::milliseconds dura(5000);//定義一個5秒的時間
	    std::this_thread::sleep_for(dura);//創(chuàng)建一個線程并開始執(zhí)行,綁定關(guān)系
	    cout << "mythread() end" << "threadid = " << std::this_thread::get_id() << endl;//卡在這里等待mythread()執(zhí)行完畢,拿到結(jié)果
		return mypar;
	}
};
 
int mythread() {
	cout << "mythread() start" << "threadid = " << std::this_thread::get_id() << endl;
	std::chrono::milliseconds dura(5000);//定義一個5秒的時間
	std::this_thread::sleep_for(dura);//創(chuàng)建一個線程并開始執(zhí)行,綁定關(guān)系
	cout << "mythread() end" << "threadid = " << std::this_thread::get_id() << endl;//卡在這里等待mythread()執(zhí)行完畢,拿到結(jié)果
	return 5;
}
 
 
int main() {
	A a;
	int tmep = 12;
	cout << "main" << "threadid = " << std::this_thread::get_id() << endl;
	std::future<int> result1 = std::async(mythread);
	cout << "continue........" << endl;
	cout << result1.get() << endl; //卡在這里等待mythread()執(zhí)行完畢,拿到結(jié)果,只能使用一次
	
	//類成員函數(shù)
	std::future<int> result2 = std::async(&A::mythread, &a, temp); //第二個參數(shù)是對象引用才能保證線程里執(zhí)行的是同一個對象
	cout << result2.get() << endl;
   //或者result2.wait(); //等待線程返回,本身不返回結(jié)果
	cout << "good luck" << endl;
	return 0;
}

我們通過向std::async()傳遞一個參數(shù),該參數(shù)是std::launch類型枚舉類型),來達到一些特殊的目的:

  1. std::lunch::deferred:
    (defer推遲,延期)表示線程入口函數(shù)的調(diào)用會被延遲,一直到std::future的wait()或者get()函數(shù)被調(diào)用時(由主線程調(diào)用)才會執(zhí)行;如果wait()或者get()沒有被調(diào)用,則不會執(zhí)行。
    重點實際上根本就沒有創(chuàng)建新線程。std::launch::deferred意思時延遲調(diào)用,并沒有創(chuàng)建新線程,是在主線程中調(diào)用的線程入口函數(shù)。
#include <iostream>
#include <future>
using namespace std;
class A {
public:
	int mythread(int mypar) {
		cout << mypar << endl;
		cout << "mythread() start" << "threadid = " << std::this_thread::get_id() << endl;
		std::chrono::milliseconds dura(5000);
		std::this_thread::sleep_for(dura);
		cout << "mythread() end" << "threadid = " << std::this_thread::get_id() << endl;
		return mypar;
	}
};

int main() {
	A a;
	int temp = 12;
	cout << "main" << "threadid = " << std::this_thread::get_id() << endl;
	cout << "continue........" << endl;
	std::future<int> result1 = std::async(std::launch::deferred, &A::mythread, &a, temp);
	cout << result1.get() << endl;
	//或者result2.wait();
	cout << "I love China!" << endl;
	return 0;
}

C++11并發(fā)與多線程筆記(9) async、future、packaged_task、promise,C++11并發(fā)與多線程筆記,c++,筆記,算法

  1. std::launch::async,在調(diào)用async函數(shù)的時候就開始創(chuàng)建新線程,不添加標記,默認用的就是默認值是 std::launch::async | std::launch::deferred 標記。
int main() {
	A a;
	int temp = 12;
	cout << "main" << "threadid = " << std::this_thread::get_id() << endl;
	cout << "continue........" << endl;
	std::future<int> result1 = std::async(std::launch::async, &A::mythread, &a, temp);//使用std::launch::async標記
	cout << result1.get() << endl;
	//或者result2.wait();
	cout << "I love China!" << endl;
	return 0;
}
  1. 同時使用std::launch::async和std::lunch::deferred標記,并不能在新線程中延遲調(diào)用。

2、std::packaged_task:打包任務(wù),把任務(wù)包裝起來

類模板,它的模板參數(shù)是各種可調(diào)用對象,通過packaged_task把各種可調(diào)用對象包裝起來,方便將來作為線程入口函數(shù)來調(diào)用。

#include <thread>
#include <iostream>
#include <future>
using namespace std;
 
int mythread(int mypar) {
	cout << mypar << endl;
	cout << "mythread() start" << "threadid = " << std::this_thread::get_id() << endl;
	std::chrono::milliseconds dura(5000);
	std::this_thread::sleep_for(dura);
	cout << "mythread() end" << "threadid = " << std::this_thread::get_id() << endl;
	return 5;
}
 
int main() {
	cout << "main" << "threadid = " << std::this_thread::get_id() << endl;
	//我們把函數(shù)mythread通過packaged_task包裝起來
    //參數(shù)是一個int,返回值類型是int
    //方法1
    std::packaged_task<int(int)> mypt(mythread);
	std::thread t1(std::ref(mypt), 1);//線程開始執(zhí)行
	t1.join();//等待線程執(zhí)行完畢
	std::future<int> result = mypt.get_future(); 
	//std::future對象里包含有線程入口函數(shù)的返回結(jié)果,這里result保存mythread返回的結(jié)果。
	cout << result.get() << endl;
	return 0;
}

可調(diào)用對象可由函數(shù)換成lambda表達式

int main() {
    //方法2,用lambda表達式
    std::packaged_task<int(int)> mypt([](int mypar){
   	cout << mypar << endl;
	cout << "mythread() start" << "threadid = " << std::this_thread::get_id() << endl;
    std::chrono::milliseconds dura(5000);
    std::this_thread::sleep_for(dura);
    cout << "mythread() end" << "threadid = " << std::this_thread::get_id() << endl;
	return 5;
    });
    std::thread t1(std::ref(mypt), 1);
	t1.join();
	std::future<int> result = mypt.get_future(); 
	//std::future對象里包含有線程入口函數(shù)的返回結(jié)果,這里result保存mythread返回的結(jié)果。
	cout << result.get() << endl;
	cout << "I love China!" << endl;
	return 0;
}

packaged_task包裝起來的可調(diào)用對象還可以直接調(diào)用,從這個角度來講,packaged_task對象也是一個可調(diào)用對象
lambda的直接調(diào)用

int main() {
    //方法2,用lambda表達式
    std::packaged_task<int(int)> mypt([](int mypar){
   	cout << mypar << endl;
	cout << "mythread() start" << "threadid = " << std::this_thread::get_id() << endl;
    std::chrono::milliseconds dura(5000);
    std::this_thread::sleep_for(dura);
    cout << "mythread() end" << "threadid = " << std::this_thread::get_id() << endl;
	return 5;
    });
    //packaged_task包裝起來的可調(diào)用對象還可以直接調(diào)用,所以從這個角度來講,pakcaged_task對象,也是一個可調(diào)用對象;
    mypt(105);//直接調(diào)用,相當于函數(shù)調(diào)用
    std::future<int> result=mypt.get_future();
    cout<<result.get()<<endl; 
	return 0;
}

包裝后存放容器里

vector<std::packaged<int(int)>> mytasks;
int main() {
    //方法2,用lambda表達式
    std::packaged_task<int(int)> mypt([](int mypar){
   	cout << mypar << endl;
	cout << "mythread() start" << "threadid = " << std::this_thread::get_id() << endl;
    std::chrono::milliseconds dura(5000);
    std::this_thread::sleep_for(dura);
    cout << "mythread() end" << "threadid = " << std::this_thread::get_id() << endl;
	return 5;
    });
	mytasks.push_back(std::move(mypt));//入容器,進去用了移動語義,入進去之后mypt就為空
	std::packaged_task<int(int)>mypt2;
	auto iter=mytask.begin();
	mypt2=std::move(*iter);//移動語義
	mytasks.erase(iter);//刪除第一個元素,迭代已經(jīng)失效了,所以后續(xù)代碼不可以再使用iter
    mypt2(105);//直接調(diào)用,相當于函數(shù)調(diào)用
    std::future<int> result=mypt2.get_future();
    cout<<result.get()<<endl; 
	return 0;
}

3、std::promise

類模板,我們能夠在某個線程中給它賦值,然后我們可以在其他線程中,把這個值取出來

#include <thread>
#include <iostream>
#include <future>
using namespace std;
 
void mythread(std::promise<int> &tmpp, int clac) {
	//做一系列復(fù)雜的操作
	clac++;
	clac *=10;
	cout << "mythread() start" << "threadid = " << std::this_thread::get_id() << endl;
	std::chrono::milliseconds dura(5000);
	std::this_thread::sleep_for(dura);
	cout << "mythread() end" << "threadid = " << std::this_thread::get_id() << endl;
	int result = clac;//保存結(jié)果
	tmp.set_value(result); //結(jié)果保存到了tmp這個對象中
	return;
}
 
int main() {
	std::promise<int> myprom;
	std::thread t1(mythread, std::ref(myprom), 180);
	t1.join(); //在這里線程已經(jīng)執(zhí)行完了
	std::future<int> fu1 = myprom.get_future(); //promise和future綁定,用于獲取線程返回值
	auto result = fu1.get();//get只能調(diào)用1次
	cout << "result = " << result << endl;
	cout<<"I love China!"<<endl;
}

總結(jié):通過promise保存一個值,在將來某個時刻我們通過把一個future綁定到這個promise上,來得到綁定的值

使用兩個子進程

#include <thread>
#include <iostream>
#include <future>
using namespace std;
 
void mythread(std::promise<int> &tmpp, int clac) {
	//做一系列復(fù)雜的操作
	clac++;
	clac *=10;
	cout << "mythread() start" << "threadid = " << std::this_thread::get_id() << endl;
	std::chrono::milliseconds dura(5000);
	std::this_thread::sleep_for(dura);
	cout << "mythread() end" << "threadid = " << std::this_thread::get_id() << endl;
	int result = clac;//保存結(jié)果
	tmp.set_value(result); //結(jié)果保存到了tmp這個對象中
	return;
}
 
void mythread2(std::future<int> &tmpf){
	auto result=tmpf.get();
	cout<<"mythread2.result"<<result<<endl;
	return;
}
 
int main() {
	std::promise<int> myprom;
	std::thread t1(mythread, std::ref(myprom), 180);
	t1.join(); //在這里線程已經(jīng)執(zhí)行完了
	std::future<int> fu1 = myprom.get_future(); //promise和future綁定,用于獲取線程返回值
	
	std::thread t2(mythread2,std::ref(ful));
	t2.join();//等mythread2線程執(zhí)行完畢
	
	cout<<"I love China!"<<endl;
}

總結(jié):第一個線程1(t1) 計算了一個結(jié)果,結(jié)果通過future對象給到第二個線程2(t2)。

注意:使用thread時,必須 join() 或者 detach() 否則程序會報異常

3、小結(jié)

我們學(xué)習(xí)這些東西的目的并不是,要把他們都用到實際開發(fā)中。
相反,如果我們能夠用最少的東西寫出一個穩(wěn)定的,高效的多線程程序,更值得贊賞。
我們?yōu)榱顺砷L必須閱讀一些高手寫的代碼,從而實現(xiàn)自己代碼的積累;文章來源地址http://www.zghlxwxcb.cn/news/detail-662720.html

到了這里,關(guān)于C++11并發(fā)與多線程筆記(9) async、future、packaged_task、promise的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • C++11并發(fā)與多線程筆記(6) unique_lock(類模板)

    unique_lock 是一個類模板。 unique_lock 比 lock_guard 靈活很多 ( 多出來很多用法 ),效率差一點,內(nèi)存占用多一些。 使用: unique_lockmutex myUniLock(myMutex); std::adopt_lock:標記作用,表示這個互斥量已經(jīng)被lock()(方便記憶:已經(jīng)被lock()收養(yǎng)了,不需要再次lock() ),即 不需要在構(gòu)造函

    2024年02月12日
    瀏覽(20)
  • C++11并發(fā)與多線程筆記(3)線程傳參詳解,detach()大坑,成員函數(shù)做線程函數(shù)

    C++11并發(fā)與多線程筆記(3)線程傳參詳解,detach()大坑,成員函數(shù)做線程函數(shù)

    在使用detach時,不推薦引用傳遞,指針傳遞肯定有問題 在創(chuàng)建線程的同時構(gòu)造臨時對象的方法傳遞參數(shù)是可行的 如果傳遞int這種基本數(shù)據(jù)類型,推薦使用 值傳遞 ,不要用引用 如果傳遞 類對象 ,避免使用隱式類型轉(zhuǎn)換,全部都是創(chuàng)建線程這一行就創(chuàng)建出 臨時對象 ,然后在

    2024年02月12日
    瀏覽(20)
  • C++11并發(fā)與多線程筆記(7) 單例設(shè)計模式共享數(shù)據(jù)分析、解決,call_once

    程序靈活,維護起來可能方便,用設(shè)計模式理念寫出來的代碼很晦澀,但是別人接管、閱讀代碼都會很痛苦 老外應(yīng)付特別大的項目時,把項目的開發(fā)經(jīng)驗、模塊劃分經(jīng)驗,總結(jié)整理成設(shè)計模式 中國零幾年設(shè)計模式剛開始火時,總喜歡拿一個設(shè)計模式往上套,導(dǎo)致一個小小的

    2024年02月12日
    瀏覽(23)
  • C++ 并發(fā)編程 | future與async

    async 函數(shù)接受兩種不同的啟動策略,這些策略在 std::launch 枚舉中定義,如下: std::launch::defered :這種策略意味著任務(wù)將在調(diào)用 future::get() 或 future::wait 函數(shù)時延遲執(zhí)行,也就是任務(wù)將在需要結(jié)果時 同步 執(zhí)行 std::launch::async :任務(wù)在單獨一個線程上 異步 執(zhí)行 默認情況下 asy

    2024年01月24日
    瀏覽(25)
  • 【C++11】future和async等

    【C++11】future和async等

    C++11的future和async等 std::async 和 std::future 是 C++11 引入的標準庫功能,用于實現(xiàn)異步編程,使得在多線程環(huán)境中更容易處理并行任務(wù)。它們可以幫助你在不同線程中執(zhí)行函數(shù),并且能夠方便地獲取函數(shù)的結(jié)果。 在之前使用線程的時候,我們沒有辦法很好的獲取到線程所執(zhí)

    2024年02月11日
    瀏覽(21)
  • 分布式集群與多線程高并發(fā)

    ? 后臺數(shù)據(jù)的處理語言有很多,Java 是對前端采集的數(shù)據(jù)的一種比較常見的開發(fā)語言。互聯(lián)網(wǎng)移動客戶端的用戶量特別大,大量的數(shù)據(jù)處理需求應(yīng)運而生??梢苿忧度胧皆O(shè)備的表現(xiàn)形式?? 很多,如 PC 端,手機移動端,智能手表,Google? 眼鏡等。Server2client 的互聯(lián)網(wǎng)開發(fā)模式比

    2024年02月08日
    瀏覽(23)
  • Python中的并發(fā)編程:多線程與多進程的比較【第124篇—多線程與多進程的比較】

    Python中的并發(fā)編程:多線程與多進程的比較【第124篇—多線程與多進程的比較】

    在Python編程領(lǐng)域中,處理并發(fā)任務(wù)是提高程序性能的關(guān)鍵之一。本文將探討Python中兩種常見的并發(fā)編程方式:多線程和多進程,并比較它們的優(yōu)劣之處。通過代碼實例和詳細的解析,我們將深入了解這兩種方法的適用場景和潛在問題。 多線程是一種輕量級的并發(fā)處理方式,適

    2024年03月14日
    瀏覽(20)
  • 再見了Future,圖解JDK21虛擬線程的結(jié)構(gòu)化并發(fā)

    再見了Future,圖解JDK21虛擬線程的結(jié)構(gòu)化并發(fā)

    Java為我們提供了許多啟動線程和管理線程的方法。在本文中,我們將介紹一些在Java中進行并發(fā)編程的選項。我們將介紹 結(jié)構(gòu)化并發(fā) 的概念,然后討論 Java 21 中一組預(yù)覽類——它使將任務(wù)拆分為子任務(wù)、收集結(jié)果并對其進行操作變得非常容易,而且不會不小心留下任何掛起的

    2024年02月05日
    瀏覽(25)
  • 【linux 多線程并發(fā)】多線程模型下的信號通信處理,與多進程處理的比較,屬于相同進程的線程信號分發(fā)機制

    ? 專欄內(nèi)容 : 參天引擎內(nèi)核架構(gòu) 本專欄一起來聊聊參天引擎內(nèi)核架構(gòu),以及如何實現(xiàn)多機的數(shù)據(jù)庫節(jié)點的多讀多寫,與傳統(tǒng)主備,MPP的區(qū)別,技術(shù)難點的分析,數(shù)據(jù)元數(shù)據(jù)同步,多主節(jié)點的情況下對故障容災(zāi)的支持。 手寫數(shù)據(jù)庫toadb 本專欄主要介紹如何從零開發(fā),開發(fā)的

    2024年01月17日
    瀏覽(22)
  • 【Java基礎(chǔ)教程】(四十二)多線程篇 · 上:多進程與多線程、并發(fā)與并行的關(guān)系,多線程的實現(xiàn)方式、線程流轉(zhuǎn)狀態(tài)、常用操作方法解析~

    【Java基礎(chǔ)教程】(四十二)多線程篇 · 上:多進程與多線程、并發(fā)與并行的關(guān)系,多線程的實現(xiàn)方式、線程流轉(zhuǎn)狀態(tài)、常用操作方法解析~

    理解進程與線程的區(qū)別; 掌握Java 中多線程的兩種實現(xiàn)方式及區(qū)別; 掌握線程的基本操作方法; 進程是程序的一次動態(tài)執(zhí)行過程,它經(jīng)歷了從代碼加載、執(zhí)行到執(zhí)行完畢的一個完整過程,這個過程也是進程本身從產(chǎn)生、發(fā)展到最終消亡的過程 。多進程操作系統(tǒng)能同時運行多

    2024年02月16日
    瀏覽(30)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包