一. 一般等待
1. sleep()
在操作系统中止此线程动作,直到渡过某个时间之后才恢复。
VOID Sleep(
DWORD dwMilliseconds // sleep time
);
实际上你不可能事先知道什么事情要等待多久,比如一个高优先级线程抢占执行的话,这个时间将变得不可预测。
要注意的是,Sleep( ),会放弃系统分配的剩余的时间片,这样 OS 就能更好的服务其他的进程和线程了。
2. busy loop
for (;;)
{
GetExitCodeThread(hThrd1, &exitCode1);
if ( exitCode1 == STILL_ACTIVE )
puts("Thread 1 is still running!");
}
忙等,是很浪费CPU时间的!因为 for( ) 在一直工作。
二. 等待线程结束
//等待一个线程结束
DWORD WaitForSingleObject(
HANDLE hHandle, // handle to object
DWORD dwMilliseconds // 最长的等待时间,INFINITE 表示无穷等待
);
// 返回值:
// WAIT_FAILED, 表示函数失败
// WAIT_OBJECT_0, 表示等待的核心对象变成激发状态
// WAIT_TIMEOUT, 表示核心对象在变成激发状态之前,时间终了了
//等待多个线程结束
DWORD WaitForMultipleObjects(
DWORD nCount, // handles 数组元素个数
CONST HANDLE *lpHandles, // handles 数组
BOOL bWaitAll, // TRUE 表示所有的handles都必须激发,此函数才得以返回
DWORD dwMilliseconds // 终了时间
);
// 返回值:
// WAIT_TIMEOUT, 时间终了
// WAIT_FAILED, 表示函数失败
// bWaitAA == TRUE, 返回值是 WAIT_OBJECT_0
// bWaitAA == FASLE, 返回值减去 WAIT_OBJECT_0,就表示数组中的哪一个 handle 被激发了
// WAIT_TIMEOUT, 表示核心对象在变成激发状态之前,时间终了了
说明:
WaitForXXXObject( ),相当于一个新版的 sleep( ),它能够在某个线程结束时被调用。
WaitForXXXObject( ),像 sleep( )一样,只会占用很少的CPU,不会出现忙等现象,所以效率会高很多。
WaitForXXXObject( ),到底在等什么?其实它等待的是一些对象被激发。
三. 被激发对象
可被 WaitForXXXObject( )使用的核心对象有两种状态:激发与未激发,WaitForXXXObject( ) 在目标变成激发状态时才返回。
比如:
Thread 当线程结束时,线程对象即被激发
Process 当进程结束时,进程对象即被激发
Event 直接受控于 SetEvent(),PulseEvent(),ResetEvent()三个函数
Mutex 如果 mutex 没有被任何线程拥有,它就处于激发状态
Semaphore 当计数器内容大于0时,semaphore处于激发状态
当出现以上对象动作时,线程对象就会被激发,此时 WaitForXXXObject( ) 就能返回。
四. 示例代码
最多用三个线程来完成六项工作
#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
DWORD WINAPI ThreadFunc(LPVOID);
#define THREAD_POOL_SIZE 3 //线程池大小为3
#define MAX_THREAD_INDEX THREAD_POOL_SIZE-1
#define NUM_TASKS 6 //共有6个任务
int main()
{
HANDLE hThrds[THREAD_POOL_SIZE];
int slot = 0;
DWORD threadId;
int i;
DWORD rc;
for (i=1; i<=NUM_TASKS; i++)
{
/* 当用完线程池里所有的线程时,要等待其它线程结束 */
if (i > THREAD_POOL_SIZE)
{
/* 等待一个线程结束 */
rc = WaitForMultipleObjects(
THREAD_POOL_SIZE,
hThrds,
FALSE,
INFINITE );
slot = rc - WAIT_OBJECT_0;
printf("Slot %d terminated\n", slot );
CloseHandle(hThrds[slot]);
}
/* 创建 6 个线程 */
hThrds[slot] = CreateThread(NULL,
0,
ThreadFunc,
(LPVOID)slot,
0,
&threadId );
printf("Launched thread #%d (slot %d)\n", i, slot);
slot++;
}
/* 等待所有的线程结束 */
rc = WaitForMultipleObjects(
THREAD_POOL_SIZE,
hThrds,
TRUE,
INFINITE );
for (slot=0; slot<THREAD_POOL_SIZE; slot++)
CloseHandle(hThrds[slot]);
printf("All slots terminated\n");
return EXIT_SUCCESS;
}
/*
* This function just calls Sleep for
* a random amount of time, thereby
* simulating some task that takes time.
*
* The param "n" is the index into
* the handle array, kept for informational
* purposes.
*/
DWORD WINAPI ThreadFunc(LPVOID n)
{
srand( GetTickCount() );
Sleep((rand()%10)*800+500);
printf("Slot %d idle\n", n);
return ((DWORD)n);
}
说明:
代码是《Win32多线程程序设计》上的,很经典。