日期:2014-05-17 浏览次数:20784 次
利用线程池(thread pool)异步调用函数时,不需显式调用 CreateThread 函数,系统会为进程自动创建线程池(thread pool)。线程池的每个线程实际运行你事先定义好的回调函数。
写到这里,也许大多人会想:怎么不直接调用众所周知的 CreateThread 函数去创建线程?这里就有必要讲一下线程池(thread pool)的机制了。
线程池(thread pool)的线程在执行完后不是立即销毁的(CreateThread创建的线程执行完成以后就销毁了),而是再次进入线程池(thread pool),等待进程请求该线程的再次执行。线程池的这种机制使得在需要创建许多线程时,性能会得到较大改善。
线程池利用内部算法能够很好地管理线程,如果线程池的线程有供大于求,它会自动销毁掉部分线程;如果线程供不应求,它会自动创建新线程。(这句话意译于《windows via C/C++》英文版Page340)
线程池的原理: (摘自网络)
来看一下线程池究竟是怎么一回事?其实线程池的原理很简单,类似于操作系统中的缓冲区的概念,它的流程如下:先启动若干数量的线程,并让这些线程都处于睡眠状态,当客户端有一个新请求时,就会唤醒线程池中的某一个睡眠线程,让它来处理客户端的这个请求,当处理完这个请求后,线程又处于睡眠状态。可能你也许会问:为什么要搞得这么麻烦,如果每当客户端有新的请求时,我就创建一个新的线程不就完了?这也许是个不错的方法,因为它能使得你编写代码相对容易一些,但你却忽略了一个重要的问题??性能!就拿我所在的单位来说,我的单位是一个省级数据大集中的银行网络中心,高峰期每秒的客户端请求并发数超过100,如果为每个客户端请求创建一个新线程的话,那耗费的CPU时间和内存将是惊人的,如果采用一个拥有200个线程的线程池,那将会节约大量的的系统资源,使得更多的CPU时间和内存用来处理实际的商业应用,而不是频繁的线程创建与销毁。
线程池异步调用回调函数五步
VOID CALLBACK WorkCallback(
_Inout_ PTP_CALLBACK_INSTANCE Instance,
_Inout_opt_ PVOID Context,
_Inout_ PTP_WORK Work
);
PTP_WORK WINAPI CreateThreadpoolWork(
_In_ PTP_WORK_CALLBACK pfnwk, //上面的WorkCallback函数的地址
_Inout_opt_ PVOID pv, //传递给WorkCallback函数的参数值,对应WorkCallback参数中的Context参数
_In_opt_ PTP_CALLBACK_ENVIRON pcbe //WorkCallback运行的环境,如果为空,则表示是默认环境。
);
VOID WINAPI SubmitThreadpoolWork(
_Inout_ PTP_WORK pwk //工作项(PTP_WORK)
);
#include <windows.h> #include <tchar.h> #include <stdio.h> #include <time.h> #define NUM_WORK_ITEM 64 #define NUM_LOOPS (1000) volatile LONG g_nCurrentTask = 0; void NTAPI SimpleCallBack(PTP_CALLBACK_INSTANCE Instance, PVOID pvContext, PTP_WORK Work) { LONG currentTask = InterlockedIncrement(&g_nCurrentTask); printf("[%5d] thread #%2d starts.\n", GetCurrentThreadId(), currentTask); printf("[%5d] thread #%2d ends.\n", GetCurrentThreadId(), currentTask); } DWORD WINAPI ThreadProc( _In_ LPVOID lpParameter &nbs