首先说packaged_task,future
他到底是个什么意思呢?其实写下来感觉就是一个存方法的容器,也可以理解为给方法娶了一个别名,下面直接上代码,看完基本上就能从用法和本质上理解个差不多了
玩法一,使用线程接收packaged_task,使用future接收结果
//线程入口函数
void threadEntryFunc(std::promise<int> &myPromise , int param1)
{
//do some arithmetic , and spend 2 seconds
param1 *= 100;
std::chrono::milliseconds dura(2000);
std::this_thread::sleep_for(dura);
//保存结果,保存到了这个promise对象中,外面能取到这个值,是因为这个promise是一个引用
myPromise.set_value(param1);
return;
}
int main()
{
std::cout << "the main thread id is " << std::this_thread::get_id() << std::endl;
//声明packaged_task<returnType(needType)> name(threadEntryFuncName)
//比如下面就是返回的是int类型的,也需要传递进去一个int类型的
//所以是<int(int)>
std::packaged_task<int(int)> myPackagedTask(threadStepInMethod);
std::thread myThread(std::ref(myPackagedTask),6);
myThread.join();
//返回一个future对象,直接就能根据future.get()得到返回的结果
std::future myFuture = myPackagedTask.get_future();
std::cout << "方式二执行结果:" << myFuture.get() << std::endl;
}
玩法二,使用lambda表达式进行线程入口函数的编写
int main()
{
//创建packaged_task的时候,直接进行lambda的编写
std::packaged_task<int(int)> myPackagedTask([](int i) {
std::cout << "thread start " << std::endl;
std::cout << "线程id:" << std::this_thread::get_id() << std::endl;
std::chrono::milliseconds dura(5000);
std::this_thread::sleep_for(dura);
std::cout << " thread end " << std::endl;
return i * 100;
});
std::thread myThread(std::ref(myPackagedTask),1);
myThread.join();
//使用future对象接收返回结果
std::future myFuture = myPackagedTask.get_future();
std::cout << "the result is " << myFuture.get() << std::endl;
}
玩法三,究其根本,packaged_task到底是个什么玩意儿?
void threadEntryFunc(std::promise<int> &myPromise , int param1)
{
//do some arithmetic , and spend 2 seconds
param1 *= 100;
std::chrono::milliseconds dura(2000);
std::this_thread::sleep_for(dura);
//保存结果,保存到了这个promise对象中,外面能取到这个值,是因为这个promise是一个引用
myPromise.set_value(param1);
return;
}
int main()
{
//声明packaged_task,
std::packaged_task<int(int)> myPackagedTask(threadEntryFunc);
//这里传进去参数,当然也可以选择创建的时候直接进行参数的传递
myPackagedTask(666);
//直接引用结果,也不创建线程,就直接调取packaged_task里面的方法
std::future myFuture= myPackagedTask.get_future();
std::cout << "the result is " << myFuture.get() << std::endl;
}
这个就有点儿意思了,这就是本质的问题了
运行结果如下
通过运行结果分析可知,直接引用,他就是一个函数调用,线程都没有创建,只不过用.get_future() 纯粹是因为要得到这个函数的返回结果,凑巧这个对象里面也有这个得到future的函数罢了 这一点和java里面的多线程很像,你重写了Thread的run()方法,但是调用时只是调用了run方法 而没有使用启动线程的start()方法,所以根本没有启动新的线程 一样的道理
玩法四,更深一层次的应用,使用容器装packaged_task
int main()
{
//创建一个装packaged_task<int(int)>的容器
std::vector<std::packaged_task<int(int)>> myVector;
//声明packaged_task<int(int)>对象
std::packaged_task<int(int)> myPackagedTask(threadStepInMethod);
//将对象放入容器
myVector.push_back(std::move(myPackagedTask));
//从容器中取出对象
auto iter = myVector.begin();
//转化为packaged_task<int(int)>对象
//*iter就是说的是指针指向的对象/值,然后使用move,使左值变为右值
std::packaged_task<int(int)> myPackagedTaskReceived = std::move(*iter);
//传递进去参数
myPackagedTaskReceived(100);
//得到结果
std::cout << "the result is " << myPackagedTaskReceived.get_future().get() << std::endl;
}
promise,在线程之间传递参数
void threadEntryFunc(std::promise<int> &myPromise , int param1)
{
//do some arithmetic , and spend 2 seconds
param1 *= 100;
std::chrono::milliseconds dura(2000);
std::this_thread::sleep_for(dura);
//保存结果,保存到了这个promise对象中,外面能取到这个值,是因为这个promise是一个引用
myPromise.set_value(param1);
return;
}
void threadEntryFunc2(std::future<int> &myParamFuture)
{
auto result = myParamFuture.get();
std::cout << "线程二中得到结果:" << result << std::endl;
}
int main()
{
//promise对象的声明
std::promise<int> myPromise;
std::thread myThread(threadEntryFunc, std::ref(myPromise), 10);
myThread.join();
std::future myFuture = myPromise.get_future();
//创建第二个线程,在第二个线程中接收promise返回的结果
std::thread myThread2(threadEntryFunc2, std::ref(myFuture));
myThread2.join();
}