1. 多线程实现的实例——闹钟功能
该实验希望设计一个闹钟功能程序,主线程计时,子线程实现定时闹钟。为了实验少等待,我们在程序中设置时钟“逢6进1”,Win32平台(VS)下程序如下:
#include<stdio.h>
#include<Windows.h>
using namespace std;
int h = 0, m = 0, s = 0;
//子线程
DWORD WINAPI Func(LPVOID lpParameter)
{
while (1)
{
if (m >= 2 && m<=5) //当在2分钟和5分钟之间就闹铃输出'a'
{
printf("%c\n", 'a');
Sleep(500);
}
}
return 0;
}
int main()
{
HANDLE hThread = CreateThread(NULL, 0, Func, NULL, 0, NULL); //创建多线程
//所谓的主线程main
while (1)
{
printf("%02d:%02d:%02d", h, m, s++);
Sleep(1000);//延时1秒
if (s == 6) //以6替代60,提前进位到分钟
{
m++;
s = 0;
}
if (m == 6) //以6替代60,提前进位到小时
{
h++;
m = 0;
}
if (m>=5)
break;
}
CloseHandle(hThread); //关闭多线程句柄,不是关闭多线程!!!!!!!
return 0;
}
2. 关于所谓主线程与子线程关系的说明
经常人们习惯把main()函数所在的线程称为主线程,而另调函数称为子线程。实际上这个称为很容易造成人们的误解,以为程序机制是以主线程为核心,而其一结束子线程也会退出。实际不然。
线程并不像进程,一个进程中的线程之间没有父子之分的,就是平行同时运行的程序,但是同享进程中几乎所有资源。所以退出一个无论什么线程都不会影响另外线程的运行。实则上这里有个错觉是因为main函数在运行完成整个main函数后return会调用进程退出代码exit(…)。整个进程结束了当然所以线程都自然会提前退出。
而如果主函数最后调用ExitThread( )仅结束当前主进程,而紧接着sleep(5000)延时,你就会发现子程序还在正常运行。
3. 关于CloseHandle()说明
所有程序在创建线程的时候有这样写:
HANDLE ThreadHandle =CreateThread(NULL,0,.....);
CloseHandel(ThreadHandle );
看似像刚创建线程就关闭,其实不然,这里需要搞清楚线程句柄(HANDLE)和线程的不同,线程句柄是一个内核对象,好比指针,指向某一个空间,然后我们可以同个这个指针变量操控那段地址,但是这个指针消除了并不代表那段空间就没了。同理,线程的生命周期和线程句柄的生命周期不一样的,线程句柄的存在就是让你有个机会对这个线程实施外部动作,诸如waitforsingleobject之类的。而另外内核对象(包括HANDLE)都是系统资源,用完就要释放,不然占用内存空间。由于当该线程创建后,几乎人们不再利用这个句柄对该线程操作,所以一般情况下人们创建完线程就释放了该句柄。
个人学习记录,由于能力和时间有限,如果有错误望读者纠正,谢谢!