目录
-
-
- 前言
- future
- 总结
-
前言
前一篇文章讲到了关于
condition_variable
的使用,但是这种方法太过于底层了,不是很方面,而且需要对调用方进行操作。这样对于程序员来说太过于麻烦,引入一个全新的接口,让被调用的线程自动进行,调用线程直接调用结果就行。这就是C++引入的
future()类
,而且这种方式可以在不同线程之间传递数据。
我们首先假设情况现在有两个线程,线程A等待线程B执行结果,线程B执行完成之后将结果返回给线程A。之前在
condition_variable
里面是在线程外定义一个全局变量,但是这样会导致数据不安全有泄露的风险。
future
首先看一个例子:
string fun_1() {
return "123";
}
int main() {
auto x = async(fun_1);
cout << "456";
cout << x.get();
}
此时x获取到的是
future<string>
类型,然后在调用.get()函数获得其中包含的值。而且线程
fun_1
只有在
.get()
时才调用。执行结果如下:
这里面有两个函数,一个是
async
,另一个是
future
。
async
使用方法和
thread类
类似,但是多了一个函数参数。
async(A, B, C,....)
:
- 其中这个A:是表示你是否创建一个新线程,参数类型是std::launch类型。
- std::launch::deferred:表示该函数会延迟启动,直到
上调用future
或wait()
;get()
- std::launch::async:表示该函数必须运行在他自己的线程上;
- std::launch::deferred | std::launch::async:表明该函数可以有具体实现来选择(默认最后一个);
- std::launch::deferred:表示该函数会延迟启动,直到
- B和C:分别是需要传入的函数和函数的参数,和thread一样,函数的参数是通过副本传入,如果需要传入引用则需要使用std::ref类。
future可以从异步任务中获取结果,一般与std::async配合使用,std::async用于创建异步任务,实际上就是创建一个线程执行相应任务。
- std::future::get获取结果,如果调用过程中,任务尚未完成,则主线程阻塞至任务完成。
- std::future::wait_for等待结果返回,wait_for可设置超时时间,如果在超时时间之内任务完成,则返回std::future_status::ready状态;如果在超时时间之内任务尚未完成,则返回std::future_status::timeout状态。
前面那个例子我们看了get()方法,我们来测试一下这个wait_for()方法:
string fun_2() {
this_thread::sleep_for(chrono::seconds(3));
return "hello";
}
int main() {
auto x = async(fun_2);
cout << "456 ";
if (x.wait_for(chrono::seconds(1)) == future_status::timeout)
cout << "time out" << endl;
else
cout << x.get();
}
线程fun_2执行时,线程睡眠3秒,主线程仅仅只等待1秒,就会出现返回time_out标志。
修改相应的等待时间参数之后得到的结果就是另外一个样子了。
总结
在使用异步线程时,采用future比condition_variable简单而且无需考虑内部实现的过程。所以在使用是尽量使用这个,而且还可以实现在不同线程之间传递数据,避免使用全局变量提高系统安全性。