1. 程式人生 > >async,future,packaged_task,promise

async,future,packaged_task,promise

一、std::async,std::future
建立後臺任務並返回值希望執行緒返回一個結果
std::async是個函式模板,用來啟動一個非同步任務,啟動起來返回std::future建立一個執行緒並開始執行對應的執行緒函式返回std::future
std::future物件裡面就有執行緒函式的返回結果,可能沒辦法馬上得到,
但是線上程執行完畢的時候,就會返回結果了

#include<future>
using namespace std;

int mythread()
{
	cout << "mythread() start. thread id =" << std::this_thread::get_id() << endl;
	std::this_thread::sleep_for(2s);//休息2秒
	cout << "mythread() end. thread id =" << std::this_thread::get_id() << endl;
	return 5;
}

int main()
{
	cout << "main id = " << std::this_thread::get_id() << endl;
	std::future<int> result = std::async(mythread);
	cout << "continue.... " << endl;
	cout << result.get() << endl;//只能呼叫一次,呼叫多次報異常

}

可以通過額外向std::async()傳遞一個引數,該引數型別是std::launch型別(列舉型別),來達到一些特殊的目的。
比如std:launch::deferred:表示執行緒入口函式呼叫被延遲到std::future的wait()或者get()函式呼叫時才執行
如果沒呼叫get()或者wait(),那麼執行緒根本就沒有建立。
並且沒有新執行緒的建立,是在主執行緒裡執行的

class A {
public:
	int mythread(int mypar)
	{
		cout << mypar << endl;
		cout << "mythread() start. thread id =" << std::this_thread::get_id() << endl;
		std::this_thread::sleep_for(2s);//休息2秒
		cout << "mythread() end. thread id =" << std::this_thread::get_id() << endl;
		return 5;
	}
};


int main()
{
	A a;
	int tmpper = 12;
	cout << "main id = " << std::this_thread::get_id() << endl;
	std::future<int> result = std::async(std::launch::deferred,&A::mythread,&a,tmpper);//第二個是引用保證是原物件
	cout << "continue.... " << endl;
	//cout << result.get() << endl;
}

在這裡插入圖片描述
在這裡插入圖片描述

std::launch::async

則是建立一個子執行緒,並且立即執行。
async()函式預設的就是async。

std::packaged_task:打包任務,把任務包裝起來
是個類模板,模板引數是各種可呼叫物件。通過packaged_task來把各種可呼叫物件包裝起來,方便將來作為執行緒入口函式用來呼叫

#include<future>
using namespace std;

int mythread(int mypar)
{
	cout << mypar << endl;
	cout << "mythread() start. thread id =" << std::this_thread::get_id() << endl;
	std::this_thread::sleep_for(2s);//休息2秒
	cout << "mythread() end. thread id =" << std::this_thread::get_id() << endl;
	return 5;
}

int main()
{
	cout << "main id = " << std::this_thread::get_id() << endl;
	std::packaged_task<int(int)> mypt(mythread);
	std::thread t1(std::ref(mypt),1);
	t1.join();
	std::future<int> result = mypt.get_future();
	cout << result.get() << endl;
	cout << "continue.... " << endl;

}
#include<future>
using namespace std;

int main()
{
	cout << "main id = " << std::this_thread::get_id() << endl;
	//packaged_task包裝起來的可呼叫物件還可以直接呼叫,所以從這個角度來講,packaged_task物件也是一個可呼叫物件
	std::packaged_task<int(int)> mypt([](int mypar) {
		cout << mypar << endl;
		cout << "mythread() start. thread id =" << std::this_thread::get_id() << endl;
		std::this_thread::sleep_for(2s);//休息2秒
		cout << "mythread() end. thread id =" << std::this_thread::get_id() << endl;
		return 5;
	});
	mypt(105);//相當於函式呼叫
	std::future<int> result = mypt.get_future();
	cout << result.get() << endl;
	cout << "continue.... " << endl;
	return 0;
}
vector<packaged_task<int(int)>> mytasks;
int main()
{
	cout << "main id = " << std::this_thread::get_id() << endl;
	//packaged_task包裝起來的可呼叫物件還可以直接呼叫,所以從這個角度來講,packaged_task物件也是一個可呼叫物件
	std::packaged_task<int(int)> mypt([](int mypar) {
		cout << mypar << endl;
		cout << "mythread() start. thread id =" << std::this_thread::get_id() << endl;
		std::this_thread::sleep_for(2s);//休息2秒
		cout << "mythread() end. thread id =" << std::this_thread::get_id() << endl;
		return 5;
	});
	mytasks.push_back(std::move(mypt));//入容器,mypt為空
	//...
	std::packaged_task<int(int)>mypt2;
	auto iter = mytasks.begin();
	mypt2 = std::move(*iter);
	mytasks.erase(iter);//刪除第一個元素,迭代器失效
	mypt2(23);
	std::future<int> result = mypt2.get_future();
	cout << result.get() << endl;

	cout << "continue.... " << endl;
	return 0;
}
#include<future>
using namespace std;

//std::promise 類模板 
//能夠在某個執行緒中給它賦值,然後在其他執行緒中把這個值取出來用。
//總結:通過promise儲存一個值,在將來某個時刻我們通過一個future繫結到這個promise來獲取這個繫結的值
void mythread(std::promise<int>&temp, int cal)
{
	cal++;
	this_thread::sleep_for(2s);
	int result = cal;//儲存結果
	temp.set_value(result);//結果儲存到temp物件中,
	return;
}

void mythread2(std::future<int> &temp)
{
	auto result = temp.get();
	cout << "mythread2 result " << result << endl;
}
int main()
{
	cout << "main id = " << std::this_thread::get_id() << endl;
	//packaged_task包裝起來的可呼叫物件還可以直接呼叫,所以從這個角度來講,packaged_task物件也是一個可呼叫物件
	std::promise<int>myprom;
	std::thread t(mythread, std::ref(myprom), 180);
	t.join();

	//獲取結果值
	std::future<int> fu1 = myprom.get_future();//獲取返回值

	std::thread t2(mythread2, std::ref(fu1));
	t2.join();

	cout << "continue.... " << endl;
	return 0;
}