文章目录
- 1.普通函数作为线程函数
- 1.1 thread
- 1.2 join()
- 1.3 detach()
- 1.4 joinable()
- 2.函数对象作为线程函数
- 3.lambda表达式作为线程函数
- 4.类成员函数作为线程函数
- 5.向线程函数传递参数
1.普通函数作为线程函数
程序运行起来,生成一个进程,其中主线程从 main() 函数开始执行,当主线程从 main() 函数返回,则整个进程执行完毕。也就是说,整个进程是否执行完毕的标志是主线程是否执行完毕。
既然主线程从 main() 函数开始执行,那么我们自己创建的线程也需要从一个函数开始运行,一旦这个函数运行完毕,我们自己创建的线程也结束运行。
1.1 thread
头文件 #include <thread>
thread 是一个类,thread td(myThread)
是利用构造函数创建了一个 thread 类对象 td
,传入参数 myThread
是一个可调用对象。
C++ 中的可调用对象可以是函数、函数指针、lambda表达式、bind创建的对象或者重载了函数调用运算符的类对象。
1.2 join()
join()
是 thread 类中的一个方法,其作用是:阻塞主线程,让主线程等待子线程执行完毕,然后子线程和主线程汇合,然后主线程再往下执行。
#include <iostream>
#include <thread>
using namespace std;
// 线程入口函数
void myThread()
{
cout << "myThread begin" << endl;
cout << "myThread running1" << endl;
cout << "myThread running2" << endl;
cout << "myThread running3" << endl;
cout << "myThread running4" << endl;
cout << "myThread running5" << endl;
cout << "myThread running6" << endl;
cout << "myThread end" << endl;
return;
}
int main()
{
thread td(myThread); // 创建了线程,线程入口函数是myThread(),myThread线程开始执行
td.join(); // 阻塞主线程并等待myThread子线程执行完,当子线程执行完毕,这个join()函数就执行完毕,主线程继续往下执行
cout << "hello world1" << endl;
cout << "hello world2" << endl;
cout << "hello world3" << endl;
cout << "hello world4" << endl;
cout << "hello world5" << endl;
cout << "hello world6" << endl;
return 0;
}
输出结果如下:
1.3 detach()
detach()
是 thread 类中的一个方法,其作用是:一旦 detach() 之后,与主线程关联的 thread 对象就会失去与主线程的关联,此时这个子线程就会驻留在后台运行(守护线程),这个子线程就相当于被 C++ 运行时库接管了,当这个子线程执行完成后,由运行时库负责清理该线程的相关资源。
一旦调用了 detach(),就不能再用 join() 了,否则系统会报异常。
#include <iostream>
#include <thread>
using namespace std;
// 线程入口函数
void myThread()
{
cout << "myThread begin" << endl;
cout << "myThread running1" << endl;
cout << "myThread running2" << endl;
cout << "myThread running3" << endl;
cout << "myThread running4" << endl;
cout << "myThread running5" << endl;
cout << "myThread running6" << endl;
cout << "myThread end" << endl;
return;
}
int main()
{
thread td(myThread); // 创建了线程,线程入口函数是myThread(),myThread线程开始执行
td.detach(); // 主线程可以不等子线程结束就先结束,子线程不会被强制结束,而是可以继续运行,驻留在后台,由C++运行时库接管
cout << "hello world1" << endl;
cout << "hello world2" << endl;
cout << "hello world3" << endl;
cout << "hello world4" << endl;
cout << "hello world5" << endl;
cout << "hello world6" << endl;
return 0;
}
输出结果如下:
1.4 joinable()
joinable()
是 thread 类中的一个方法,其作用是:判断线程是否可以成功使用 join() 或 detach()。
- 如果返回 true,表示可以调用 join() 或 detach();
- 如果返回 false,表示已经调用过 join() 或 detach(),不能再调用 join() 或 detach() 了。
2.函数对象作为线程函数
#include <iostream>
#include <thread>
using namespace std;
class A
{
public:
int m_i;
A(int i) : m_i(i)
{
cout << "构造函数执行,this = " << this << endl;
}
A(const A& a) : m_i(a.m_i)
{
cout << "拷贝构造函数执行,this = " << this << endl;
}
~A()
{
cout << "析构函数执行,this = " << this << endl;
}
// 线程入口函数
void operator()(int num)
{
cout << "m_i = " << m_i << ",num = " << num << ",this = " << this << endl;
}
};
int main()
{
int i = 100;
A a(i);
thread td(a, 18);
td.join();
cout << "hello world1" << endl;
cout << "hello world2" << endl;
cout << "hello world3" << endl;
return 0;
}
输出结果如下:
3.lambda表达式作为线程函数
#include <iostream>
#include <thread>
using namespace std;
int main()
{
// 线程入口函数
auto myThread = [] {
cout << "myThread begin" << endl;
cout << "myThread running1" << endl;
cout << "myThread running2" << endl;
cout << "myThread running3" << endl;
cout << "myThread running4" << endl;
cout << "myThread running5" << endl;
cout << "myThread running6" << endl;
cout << "myThread end" << endl;
};
thread td(myThread);
td.join();
cout << "hello world1" << endl;
cout << "hello world2" << endl;
cout << "hello world3" << endl;
return 0;
}
输出结果如下:
4.类成员函数作为线程函数
#include <iostream>
#include <thread>
using namespace std;
class A
{
public:
int m_i;
A(int i) : m_i(i)
{
cout << "构造函数执行,this = " << this << endl;
}
A(const A& a) : m_i(a.m_i)
{
cout << "拷贝构造函数执行,this = " << this << endl;
}
~A()
{
cout << "析构函数执行,this = " << this << endl;
}
// 线程入口函数
void work(int num)
{
cout << "m_i = " << m_i << ",num = " << num << ",this = " << this << endl;
}
};
int main()
{
A a(100);
thread td(&A::work, a, 18);
td.join();
return 0;
}
输出结果如下:
5.向线程函数传递参数
关于向线程函数传递参数的具体细节,可以看下这篇文章:https://www.cnblogs.com/chen-cs/p/13056703.html