多线程,Multi-Thread。移步别处理解Thread和Process。多线程可用多种API实现,这里用Win32 API实现最简单的多线程,线程彼此独立,不涉及线程间的数据共享。
先直接上程序:
#include <stdio.h>
#include <windows.h>
#include <process.h>
#include <string>
#include <iostream>
class ThreadX
{
private:
std::string threadName;
int loopStart;
int loopEnd;
int loopStep;
public:
ThreadX(int x, int y, int z) : loopStart(x), loopEnd(y), loopStep(z) { }
void SetThreadName(std::string name)
{
threadName = name;
}
static unsigned __stdcall ThreadEntryPoint(void* pThis)
{
ThreadX* pTh = (ThreadX*)pThis;
pTh->StartUp();
return 1;
}
void StartUp()
{
for (int i = loopStart; i < loopEnd; ++i)
{
if (i % loopStep == 0)
{
//std::cout << threadName << ": " << i << std::endl;
printf("%s : %d \n", threadName.c_str(), i);
}
}
printf("%s terminating...\n", threadName.c_str());
}
};
int main()
{
ThreadX* obj1 = new ThreadX(0, 1000000, 20000);
obj1->SetThreadName("Thread1");
HANDLE hThread1;
unsigned thread1Id;
hThread1 = (HANDLE)_beginthreadex(NULL,
0,
ThreadX::ThreadEntryPoint,
obj1,
CREATE_SUSPENDED,
&thread1Id);
if (hThread1 == NULL)
{
printf("Failed to create Thread 1. \n");
}
DWORD dwExitCode;
GetExitCodeThread(hThread1, &dwExitCode);
printf("initial thread 1 exit code = %d \n", dwExitCode);
ThreadX* obj2 = new ThreadX(-1000000, 0, 20000);
obj2->SetThreadName("Thread2");
HANDLE hThread2;
unsigned thread2Id;
hThread2 = (HANDLE)_beginthreadex(NULL,
0,
ThreadX::ThreadEntryPoint,
obj2,
CREATE_SUSPENDED,
&thread2Id);
if (hThread2 == NULL)
{
printf("Failed to create Thread 1. \n");
}
GetExitCodeThread(hThread1, &dwExitCode);
printf("initial thread 2 exit code = %d \n", dwExitCode);
ResumeThread(hThread1);
ResumeThread(hThread2);
WaitForSingleObject(hThread1, INFINITE);
WaitForSingleObject(hThread2, INFINITE);
GetExitCodeThread(hThread1, &dwExitCode);
printf("thread 1 exit with code : %d \n", dwExitCode);
GetExitCodeThread(hThread2, &dwExitCode);
printf("thread 2 exit with code : %d \n", dwExitCode);
CloseHandle(hThread1);
CloseHandle(hThread2);
delete(obj1);
obj1 = NULL;
delete(obj2);
obj2 = NULL;
system("pause");
return 0;
}
运行结果如下:
记录以下几点。
1.
hThread1 = (HANDLE)_beginthreadex(NULL,
0,
ThreadX::ThreadEntryPoint,
obj1,
CREATE_SUSPENDED,
&thread1Id);
ResumeThread(hThread1);
WaitForSingleObject(hThread1, INFINITE);
GetExitCodeThread(hThread1, &dwExitCode);
CloseHandle(hThread1);
这个Sample里用到的关于多线程的Win32 API就上面的几个粗体标示的函数。
注意:
(1)用_beginthreadex 而非CreateThread,因为CreateThread用于CRT时会导致内存泄露。
官方说明如下:http://msdn.microsoft.com/en-us/library/windows/desktop/ms682453(v=vs.85).aspx
“A thread in an executable that calls the C run-time library (CRT) should use the _beginthreadex and_endthreadex functions for thread management rather than CreateThread and ExitThread; this requires the use of the multithreaded version of the CRT. If a thread created using CreateThread calls the CRT, the CRT may terminate the process in low-memory conditions.”
(2) _beginthreadex 创建的进程被Suspend了,所以才需要后面的ResumeThread(hThread1) 将进程唤醒。
(3)当线程还存活时,GetExitCodeThread返回的是259,当线程运行结束时,返回的是1.
2.
输出信息时,推荐用printf,不容易被其他进行插断。用cout时,stream容易在不同Thread中跳转。 如果将StartUp()函数里的信息输入用注释的那行代替printf那行,运行结果容易出现这种问题:
3.
为了显示出多线程的同时运行,即最终的运行结果里Thread1和Thread2的信息穿插输出,需要保证StartUp()里循环的次数够多才输出信息,否则其他Thread来不及插队打印信息。
比如,将
ThreadX* obj1 = new ThreadX(0, 1000000, 20000);
ThreadX* obj2 = new ThreadX(-1000000, 0, 20000);
改为
ThreadX* obj1 = new ThreadX(10, 600, 7);
ThreadX* obj2 = new ThreadX(10001, 10900, 9);
运行结果就变为:
即看起来像是一个线程运行结束后才开始另一个线程。 不是我们想看到的效果-_-
最后,推荐一个多线程入门的教程:http://www.codeproject.com/Articles/14746/Multithreading-Tutorial ,讲解和例子都很棒,尤其是前面4个例子。