在文章C++11线程库 (一) 构造函数及其成员中我们知道我们有一下构造方法:
thread() noexcept;//since c++11
thread(thread&& other) noexcept;//since c++11
template<class Function,class ...Args>
explicit thread(Function &&f,Args && ...args);//since c++11
thread(const thread&)=delete;//since c++11
一共四个,第一个是默认构造,构造一个什么也不做的线程对象;第二个是std::move()会调用的移动构造函数;第三个是类模板,表示使用一个函数对象和若干个参数生成对应的线程类;第四个是拷贝构造函数,默认是不能拷贝的。
第三个是创建一个线程对象的基本方法,他需要
- 一个函数对象
- 零个或者多个参数
函数对象可以由函数模板产生,其定义:
template< class >
class function; /* undefined */
(since C++11)
template< class R, class... Args >
class function<R(Args...)>;//用R类实例化函数对象
给定一个类和对应参数,类模板产生一个std::function类。模板的class R参数有一定的要求,常见满足要求的类有:
- 普通函数
- lambda表达式
- bind表达式
- 其他可调用对象(如仿函数)
- 成员函数指针
- 成员函数数据成员(类数据成员?)
Notes
The arguments to the thread function are moved or copied by value. If a reference argument needs to be passed to the thread function, it has to be wrapped (e.g. with std::ref or std::cref).
Any return value from the function is ignored. If the function throws an exception, std::terminate is called. In order to pass return values or exceptions back to the calling thread, std::promise or std::async may be used.
实例:创建两个线程分别打印奇数和偶数
#include <iostream>
#include <thread>
using namespace std;
void show_even()
{
for(int i=0;i<10;i+=2)
{
cout<<i;
}
};
void show_odd()
{
for(int i=1;i<10;i+=2)
{
cout<<i;
}
}
int main()
{
thread th1(show_odd);
thread th2(show_even);
th1.join();
th2.join();
return 0;
}
每次运行的结果都不一样,任取三次结果:0246813579
1357902468
1350247968
。cpu每次只会在一个线程中执行,如果处理的速度足够简单,可能一个线程所有内容完成了,另一个线程还没开始。
对于一个简单的执行内容,使用lambda创建一个可调用对象更为合适:
int main()
{
thread th1([](){
for(int i=0;i<10;i+=2){
cout<<i;}});
thread th2([](){
for(int i=1;i<10;i+=2){
cout<<i;}});
th1.join();
th2.join();
return 0;
}
不用想函数名,不用专门写一个函数,blabla.