特别声明,本系列学习教程来自【阿发你好】 官网地址:阿发你好
版权声明:本文为博主-黄可可(hkkhuang)-原创文章,未经博主允许可转载,但请标明出处,谢谢!
1、线程的创建与启动
1、1线程的创建与启动
(1)定义Buddhist 、Confucian 类,继承于OS_Thread,重写线程主函数Routine()
(2)使用这个类
Buddhist b;
b.Run();
//设置断点,观察 资源监视器 线程数量 2
Confucian c;
c.Run();
//设置断点,观察 资源监视器 线程数量 3
注:在多数系统上, 线程的创建和启动是一个连续的动作。
线程属于系统级资源,可以在一个“资源监视器”中查看一个进程中的线数。
打开方法: 任务管理器 | 性能 | 资源管理器
示例:
//定义一个类
class Buddhist :public OS_Thread
{
private:
virtual int Routine()
{
//线程体:执行他的任务
for (int i = 0; i < 100; i++)
{
printf("和尚念经。。。\n");
OS_Thread::Sleep(1); //静态函数
}
return 0;
}
};
//定义一个类
class Confucian :public OS_Thread
{
private:
virtual int Routine()
{
//线程体:执行他的任务
for (int i = 0; i < 500; i++)
{
printf("秀才读书。。。\n");
OS_Thread::Sleep(1); //静态函数
}
return 0;
}
};
int main()
{
//设置断点,观察 资源监视器 线程数量 1
Buddhist b;
b.Run();
//设置断点,观察 资源监视器 线程数量 2
Confucian c;
c.Run();
//设置断点,观察 资源监视器 线程数量 3
//两个子线程同时工作,主线程也可以工作,不影响
printf("-------------main主线程开始工作-------------\n");
for (int i = 0; i < 100; i++)
{
printf("管理人员开始工作。。。。。。。。。\n");
//主线程在执行的过程中也是需要sleep,让出cpu
OS_Thread::Sleep(1);
}
getchar();
return 0;
}
1.2、不要把创建线程和”函数调用”混淆
MyTask task;
task.Run(); // 这是创建线程
而不是
task.Routine(); // 这是函数调用
区别:创建线程是操作系统来完成的,它创建一个线程实体,该线程的主函数是Routine() 即线程的入口。
1.3、 Run()
Run(): 相当于对OS说:
“请创建一个线程,入口函数为Routine()”
OS则根据程序员的要求,创建一个线程实体来运行,线程的主函数就是Routine()。
2、“线程”的两种语境
两种语境:
(1) OS_Thread
它是一个C++类/对象,封装了线程相关数据和操作;
(2) 线程实体
由操作系统创建的实体(跟进程类比)。通常我们说的线程指的是这个,它是一个运行时的概念。
Buddhist b; // 这只是创建一个C++里的对象 b.Run(); // 这里"线程"才被真正的创建 Run()的内部告诉OS来创建一个线程
3、线程是有限的资源
一个进程中的最大线程数是有限制的,一般为几千到几万。但是,在工程实践中一般线程数最多是几十个。线程数不宜过多,因为线程调度本身也是有成本的。
注: 如果你发现必须使用上百个线程,那往往意味着你的设计存在问题。