一上来就用一段代码来开启这节课...
#include <thread>
#include <iostream>
using namespace std;
void function_1()
{
cout << "Hello world!" << endl;
}
int main(int argc, char** argv)
{
std::thread t1(function_1);
for(int i=0;i<100;++i)
{
cout << "from main:" << i << endl;
}
t1.join();
return 0;
}
编译的指令和(1)介绍的一样,之后就不再提及了.而此时线程启动运行的时间不一定,可能会在主线程不同的输出过程中执行.而这里如果,在主线程中的for语句出现异常的话,那么t1对象则会被销毁,也就是没有机会完成它自己的使命了,那该怎么办呢?哦,很简单,那就捕捉异常罗,哈哈.
#include <thread>
#include <iostream>
using namespace std;
void function_1()
{
cout << "Hello world!" << endl;
}
int main(int argc, char** argv)
{
std::thread t1(function_1);
try {
for(int i=0;i<100;++i)
{
cout << "from main:" << i << endl;
}
}
catch(...)//用于捕捉所有异常
{
t1.join();
throw;//抛出异常
}
t1.join();
return 0;
}
接下来,就介绍到函数并不是构造线程的唯一方式,这里还可以用任何可调用对象来进行构造线程.这里先构造一个类来进行构造线程.
#include <thread>
#include <iostream>
using namespace std;
void function_1()
{
cout << "Hello world!" << endl;
}
class Factor {
public:
void operator()(){
for(int i=0;i<100;++i)
cout << "from t1: " << i << endl;
}
};
int main(int argc, char** argv)
{
Factor fct;
std::thread t1(fct);
try {
for(int i=0;i<100;++i)
{
cout << "from main:" << i << endl;
}
}
catch(...)
{
t1.join();
throw;
}
t1.join();
return 0;
}
这里两个线程之间的输出没有什么规律,可能每一次运行,输出的顺序都不太一样.
//也可以将
Factor fct;
std::thread t1(fct);
//改成
std::thread t1((Factor()));
//效果一样
然后,就介绍新的东西,也就是在线程构造的时候传入参数,代码如下所示.
#include <thread>
#include <iostream>
#include <string>
using namespace std;
void function_1()
{
cout << "Hello world!" << endl;
}
class Factor {
public:
void operator()(string msg){
for(int i=0;i<100;++i)
cout << "from t1: " << msg << endl;
}
};
int main(int argc, char** argv)
{
string msg = "hello t1 thread!";
std::thread t1((Factor()),msg);
try {
for(int i=0;i<100;++i)
{
cout << "from main:" << i << endl;
}
}
catch(...)
{
t1.join();
throw;
}
t1.join();
return 0;
}
哦,听说线程里传参数了,那你试试改改参吧,哈哈.
//注释:在运行这里的代码的时候,视频中可以直接运行,即不用std::ref(),而我则一直出错,所以只能直接上有效代码.视频中如果不用std:ref(msg),则此时还是传参的过程,即不能更改msg的信息.
#include <thread>
#include <iostream>
#include <string>
using namespace std;
void function_1()
{
cout << "Hello world!" << endl;
}
class Factor {
public:
void operator()(string& msg){
cout << "from t1: " << msg << endl;
msg = "I have changed from t1~";
}
};
int main(int argc, char** argv)
{
string msg = "hello t1 thread!";
std::thread t1((Factor()),std::ref(msg));//注释说的是这个地方
t1.join();
cout << "from main:" << msg << endl;
return 0;
}
上面这个代码其实已经涉及到了共享内存,即msg的共享,会产生数据竞争的问题.接着,介绍另外一种传参方式,既高效,又方便,即std::move(msg),也就是将msg从主线程移动到子线程中,其实还有很多类型只能移动,不能拷贝,例如thread对象.
//举个例子
thread t1((Factor()),std::move(msg));
//thread t2 = t1;//会出错,因为不能拷贝
thread t2 = std::move(t1);//才是正确打开方式
t2.join();//这个地方也不再是t1,因为t1已经为空了
还有就是如果想要查询线程的id,则可以在线程执行代码中使用语句
cout << this_thread::get_id();//显示当前id号
//或者可以用t1.get_id()来查询
标准库提供了函数来查询当前CPU可以最多用多少个线程进行并发编程.
std::thread::hardware_concurrency();