4.1 线程异步和通信
4.1.1 promise和future
promise 用于异步传输变量
std::promise 提供存储异步通信的值,再通过其对象创建的std::future异步获得结果 std::promise 只能使用一次。void set_value(_Ty&& _Val) 设置传递值,智能调用一次
std:future 提供访问异步操作结果的机制
get()阻塞等待promise set_value的值
代码演示
void TestFuture(promise<string> p) {ps.set_value("TestFuture value");}int main(){}
#include <future>#include <iostream>#include <string>#include <thread>using namespace std;void TestFuture(promise<string> p){cout << "begin TestFuture" << endl;this_thread::sleep_for(3s);cout << "begin set value" << endl;p.set_value("TestFuture value");this_thread::sleep_for(3s);cout << "end TestFuture" << endl;}int main(int argc, char* argv[]){// 异步函数变量promise<string> p;// 用来获取线程异步值获取auto future = p.get_future();auto th = thread(TestFuture, move(p)); // 将p转移到线程函数中,不能使用复制(直接传入p)cout << "begin future.get()" << endl;cout << "future get() = " << future.get() << endl;cout << "end future.get()" << endl;th.join();getchar();return 0;}/*begin future.get()begin TestFuture // 等到了3sbegin set value // 开始读值, 调用get的时候是阻塞的,等调用完,子线程才结束future get() = TestFuture valueend future.get()end TestFuture*/
4.1.2 packaged_task 异步调用函数打包
- ackaged_task 包装函数为一个对象,用于异步调用。其返回值能通过std::future 对象访问
- 与bind的区别,可异步调用,函数访问和获取返回值分开调用
```cpp
include
include
include
include
using namespace std;
string TestPack(int index) { cout << “begin test pack “ << index << endl; this_thread::sleep_for(2s); // 模拟业务逻辑 return “TestPack return”; }
int main(int argc, char* argv[])
{
packaged_task
// 以上同时打印出来, 是同步调用的cout << "begin result get" << endl;cout << "result get " << result.get() << endl;getchar();return 0;
}
/ begin test pack 100 begin result get result get TestPack return /
加上线程,可看到 get() 那是堵塞的
```cpp
#include <future>
#include <iostream>
#include <string>
#include <thread>
using namespace std;
string TestPack(int index)
{
cout << "begin test pack " << index << endl;
this_thread::sleep_for(2s); // 模拟业务逻辑
return "TestPack return";
}
int main(int argc, char* argv[])
{
packaged_task<string(int)> task(TestPack); // 模板里是函数类型 返回值类型参数类型
auto result = task.get_future(); // 返回值结果和上面模板的一样
thread th(move(task), 100);
cout << "begin result get" << endl;
cout << "result get " << result.get() << endl;
th.join();
getchar();
return 0;
}
/*
begin result get
result get begin test pack 100
TestPack return
*/
#include <future>
#include <iostream>
#include <string>
#include <thread>
using namespace std;
string TestPack(int index)
{
cout << "begin test pack " << index << endl;
this_thread::sleep_for(2s); // 模拟业务逻辑
return "TestPack return";
}
int main(int argc, char* argv[])
{
packaged_task<string(int)> task(TestPack); // 模板里是函数类型 返回值类型参数类型
auto result = task.get_future(); // 返回值结果和上面模板的一样
thread th(move(task), 100);
cout << "begin result get" << endl;
//测试是否超时
for (int i = 0; i < 30; i++) { // 如果该成1秒,会看出它是超时的
result.wait_for(100ms);
}
if (result.wait_for(100ms) == future_status::timeout) {
cout << "wait result timeout" << endl;
} else {
cout << "result get " << result.get() << endl;
}
th.join();
getchar();
return 0;
}
4.1.3 async
C++11 异步运行一个函数,并返回保有其结果的 std::future
- launch::deferred 延迟执行,在调用wait和get时,调用函数代码
- launch::async 创建线程(默认)
- 返回的线程函数的返回值类型的std::future
(std:future<线程函数的返回值类型>) - re.get() 获取结果,会堵塞等待
```cppdouble result = 0; cout << "Async task with lambda triggered, thread: " << this_thread::get_id() << endl; // auto f2 = async(launch::async, [&result](){});include
include
include
include
using namespace std;
string TestAsync(int index) { cout << index << “ begin in TestAsync: “ << this_thread::get_id() << endl; this_thread::sleep_for(2s); return “TestAsync string return.”; }
int main(int argc, char* argv[]) { // 创建异步线程
// 情况一:不创建线程启动异步任务
cout << "main thread id: " << this_thread::get_id() << endl;
auto future = async(launch::deferred, TestAsync, 100);
this_thread::sleep_for(100ms);
cout << "begin future get" << endl;
cout << "future.get() = " << future.get() << endl;
cout << "end future get" << endl;
/*
main thread id: 1
begin future get
future.get() = 100 begin in TestAsync: 1
TestAsync string return.
end future get
*/
// 情况2:创建线程启动异步任务
cout << "main thread id: " << this_thread::get_id() << endl;
auto future2 = async(TestAsync, 101);
this_thread::sleep_for(100ms);
cout << "begin future get" << endl;
cout << "future.get() = " << future2.get() << endl;
cout << "end future get" << endl;
getchar();
return 0;
}
```
