工作中自己写多线程thread用的还是多一点,有天在github上看到c++线程池的实现用的是std::async,就查了下相关知识记录一下。
async最重要的特点就是线程间通信,取线程的返回值比较方便。async的返回值会存在std::future里面,而这里只记录下常用的功能。
std::async的原型为:
async(std::launch::async | std::launch::deferred, f, args…)
其中async表示立刻执行,deferred表示延迟执行,f表示函数,args表示函数参数
下面第两个个例子就是通过int类型的future接收返回的8
std::future<int> f1 = std::async(std::launch::async, [](){
return 8;
});
cout<<f1.get()<<endl; //output: 8
std::future<int> f2 = std::async(std::launch::async, [](){
cout<<8<<endl;
});
f2.wait(); //output: 8
其中有两个future的方法get()和wait(),get()会让当前线程等待直到有返回值,wait()则只会等线程结束。future解决了获取线程返回值的问题,那么std::promise则可以用来解决线程间通信的问题
#include <iostream>
#include <future>
#include <chrono>
void Thread_Fun1(std::promise<int> &p)
{
//为了突出效果,可以使线程休眠5s
std::this_thread::sleep_for(std::chrono::seconds(5));
int iVal = 233;
std::cout << "传入数据(int):" << iVal << std::endl;
//传入数据iVal
p.set_value(iVal);
}
void Thread_Fun2(std::future<int> &f)
{
//阻塞函数,直到收到相关联的std::promise对象传入的数据
auto iVal = f.get(); //iVal = 233
std::cout << "收到数据(int):" << iVal << std::endl;
}
int main()
{
//声明一个std::promise对象pr1,其保存的值类型为int
std::promise<int> pr1;
//声明一个std::future对象fu1,并通过std::promise的get_future()函数与pr1绑定
std::future<int> fu1 = pr1.get_future();
//创建一个线程t1,将函数Thread_Fun1及对象pr1放在线程里面执行
std::thread t1(Thread_Fun1, std::ref(pr1));
//创建一个线程t2,将函数Thread_Fun2及对象fu1放在线程里面执行
std::thread t2(Thread_Fun2, std::ref(fu1));
//阻塞至线程结束
t1.join();
t2.join();
return 1;
}
上述例子中的第二个线程就会在get()处等待第一个线程中的promise使用set_value(int)设置值后再开始下面代码的执行,这就实现了线程间的通信功能,
顺便说下std::packaged_task,这个就相当于多了个future返回值的std::function,如下
#include <iostream>
#include <future>
#include <chrono>
#include <functional>
int Test_Fun(int a, int b, int &c)
{
//a=1,b=2,c=0
//突出效果,休眠5s
std::this_thread::sleep_for(std::chrono::seconds(5));
//c=233
c = a + b + 230;
return c;
}
int main()
{
//声明一个std::packaged_task对象pt1,包装函数Test_Fun
std::packaged_task<int(int, int, int&)> pt1(Test_Fun);
//声明一个std::future对象fu1,包装Test_Fun的返回结果类型,并与pt1关联
std::future<int> fu1 = pt1.get_future();
//声明一个变量
int c = 0;
//创建一个线程t1,将pt1及对应的参数放到线程里面执行
std::thread t1(std::move(pt1), 1, 2, std::ref(c));
//阻塞至线程t1结束(函数Test_Fun返回结果)
int iResult = fu1.get();
std::cout << "执行结果:" << iResult << std::endl; //执行结果:233
std::cout << "c:" << c << std::endl; //c:233
return 1;
}