1. 简单用例
future和promise的作用是在不同线程之间传递数据。
简单的例子:假设线程1需要线程2的数据,那么组合使用方式如下:
- 线程1初始化一个promise对象和一个future对象, promise传递给线程2, 相当于线程2对线程1的一个承诺,future相当于一个接受一个承诺,用来获取未来线程2传递的值。
- 如果值未返回,则一直会阻塞。
#include <iostream> // std::cout, std::endl
#include <thread> // std::thread
#include <string> // std::string
#include <future> // std::promise, std::future
#include <chrono> // seconds
using namespace std::chrono;
void read(std::future<std::string> *future) {
// future会一直阻塞,直到有值到来
std::cout << future->get() << std::endl;
}
int main() {
// promise 相当于生产者
std::promise<std::string> promise;
// future 相当于消费者, 右值构造
std::future<std::string> future = promise.get_future();
// 另一线程中通过future来读取promise的值
std::thread thread(read, &future);
// 让read等一会儿:)
std::this_thread::sleep_for(seconds(1));
//
promise.set_value("hello future");
// 等待线程执行完成
thread.join();
return 0;
}
// 控制台输: hello future
2. 并行例子1
在rpc调用接口,经常会遇到一种情况就是, 同时从多个rpc接口获取内容,然后将数据在主线程中进行合并。一般情况下,如果cpu耗时的任务启用线程来执行比较合适,而io耗时的任务一般采用协程来处理。这里使用promise和future解决这个问题。
#include<thread>
#include<future>
#include<iostream>
using namespace std;
// 子线程
void TaskOne(std::promise<std::string> *p) {
p->set_value("one");
}
// 子线程
void TaskTwo(std::promise<std::string> *p) {
p->set_value("two");
}
int main() {
std::promise<std::string> p1;
std::promise<std::string> p2;
std::future<std::string> f1 = p1.get_future();
std::future<std::string> f2 = p2.get_future();
std::thread t1 = std::thread(TaskOne, &p1);
std::thread t2 = std::thread(TaskTwo, &p2);
t1.join();
t2.join();
// 主线程把结果合并
cout << f1.get() << endl;
cout << f2.get() << endl;
}
g++ test.cpp -lpthread -std=c++11
2. 并行例子2
有时候需要传递结构体,而不仅仅一个数组。
#include<thread>
#include<future>
#include<iostream>
#include<string>
using namespace std;
struct Data {
int number = 1;
string str = "data";
};
// 子线程
void TaskOne(std::promise<Data> *p) {
Data data;
data.number = 2;
p->set_value(data);
}
// 子线程
void TaskTwo(std::promise<std::string> *p) {
p->set_value("two");
}
int main() {
std::promise<Data> p1;
std::promise<std::string> p2;
std::future<Data> f1 = p1.get_future();
std::future<std::string> f2 = p2.get_future();
std::thread t1 = std::thread(TaskOne, &p1);
std::thread t2 = std::thread(TaskTwo, &p2);
t1.join();
t2.join();
// 主线程把结果合并
auto data = f1.get();
cout << data.number << endl;
cout << data.str << endl;
cout << f2.get() << endl;
}
g++ test.cpp -lpthread -std=c++11
3. 并行例子3
有时候还需要包装成类,在类中怎么实现呢?因为thread的执行函数只能是全局静态的,因此类的私有成员不可直接调用,这里使用bind方法实现静态函数的定义。具体如下:
#include<thread>
#include<future>
#include<iostream>
#include<string>
using namespace std;
class TestThread {
public:
struct Data {
int number = 1;
string str = "data";
};
void Run() {
std::promise<Data> p1;
std::promise<std::string> p2;
std::future<Data> f1 = p1.get_future();
std::future<std::string> f2 = p2.get_future();
std::thread t1 = std::thread(std::bind(&TestThread::TaskOne, this, &p1));
std::thread t2 = std::thread(std::bind(&TestThread::TaskTwo, this, &p2));
t1.join();
t2.join();
// 主线程把结果合并
auto data = f1.get();
cout << data.number << endl;
cout << data.str << endl;
cout << f2.get() << endl;
}
// 子线程
void TaskOne(std::promise<Data> *p) {
Data data;
data.number = 2;
p->set_value(data);
}
// 子线程
void TaskTwo(std::promise<std::string> *p) {
p->set_value("two");
}
};
int main() {
//TestThread* t = new TestThread();
//t->Run();
TestThread t;
t.Run();
}
3. 并行例子4
rpc传输协议大部分以pb协议为主,通常需要传递的是一个pb的数据结构,这里提供使用pb的结构体,实现数据传输。
- 安装pb
protobuf-cpp-3.8.0.zip
- 设计pb文件
package mt;
syntax = "proto3";
message SearchRequest {
string query = 1;
int32 page_number = 2;
int32 result_per_page = 3;
}
- 生成C++文件
/usr/local/bin/protoc -I=. --cpp_out=. test.proto
- 简单makefile设计
objects = test.pb.o test.o
main : $(objects)
cc -o main $(objects) -L/usr/local/lib -lprotobuf -lpthread -lstdc++
test.o : test.cpp test.pb.h
cc -c test.cpp
test.pb.o : test.pb.cc test.pb.h
cc -c test.pb.cc
clean :
rm main $(objects)
- 代码实现
#include<thread>
#include<future>
#include<iostream>
#include<string>
#include "test.pb.h"
using namespace std;
using namespace mt;
class TestThread {
public:
void Run() {
std::promise<SearchRequest> p1;
std::promise<std::string> p2;
std::future<SearchRequest> f1 = p1.get_future();
std::future<std::string> f2 = p2.get_future();
std::thread t1 = std::thread(std::bind(&TestThread::TaskOne, this, &p1));
std::thread t2 = std::thread(std::bind(&TestThread::TaskTwo, this, &p2));
t1.join();
t2.join();
// 主线程把结果合并
auto data = f1.get();
cout << data.query() << endl;
cout << f2.get() << endl;
}
// 子线程
void TaskOne(std::promise<SearchRequest> *p) {
SearchRequest data;
data.set_query("test");
p->set_value(data);
}
// 子线程
void TaskTwo(std::promise<std::string> *p) {
p->set_value("two");
}
};
int main() {
//TestThread* t = new TestThread();
//t->Run();
TestThread t;
t.Run();
}