您的位置:首页 > 其它

Windows 2008 Server线程池前瞻(原创)

2017-10-10 14:17 288 查看
       没有什么能让我如此的着迷和口水直流了,可是我的机器却无法安装Windows 2008 Server,因为俺没钱升级它。所以我所有关于这个Windows 2008 Server的知识都是来自MSDN,在那里,它被叫作Longhorn(长角牛),其实我一直没搞懂这个牛究竟长得啥样子,我估计不好看。因为好看的东西肯定都被人拍成写真集,到处散播了。
       在我看Windows从2000 Server开始追加的线程池函数时,我一直感慨——开发者真正能控制的东西实在是太少了。比如那个有名的函数
BOOL WINAPI QueueUserWorkItem(   LPTHREAD_START_ROUTINE Function,   PVOID Context,   ULONG Flags ); 我一直没搞懂它为什么起了这么个奇怪的名字,它没有给我指定追加线程池线程的权限,就这么一个函数,只告诉我排队,但是我要是不想排队这个WorkItem(瞧瞧,多难听的名字)了,我几乎没有办法,他排进去了,你无法把它从那个Queue里干掉。你不知道线程池有多少线程,你也不知道他们耗费了多少资源,你无法设定安全描述符,你不能暂停他们,你不能彻底的删除它们等等,你不能做很多事,你唯一能做的就是指定一个奇怪的标志,关于这个标志文档和定义中的常量都不一样多。这也是Windows 2003 Server上的线程池的状态,我唯一的感觉就是好弱啊,我只能眼睁睁的看着我的线程函数被活生生的从这道门送进了一个密不透风的黑盒子。 MSDN的传说中,这一切在"长角牛"上得到了改观,它提供了更强大的线程池函数:  
FeatureCurrent API
SynchCloseThreadpoolWait
CreateThreadpoolWait
SetThreadpoolWait
WaitForThreadpoolWaitCallbacks
WorkCloseThreadpoolWork
CreateThreadpoolWork
SubmitThreadpoolWork
TrySubmitThreadpoolCallback
WaitForThreadpoolWorkCallbacks
TimerCloseThreadpoolTimer
CreateThreadpoolTimer
IsThreadpoolTimerSet
SetThreadpoolTimer
WaitForThreadpoolTimerCallbacks
I/OCancelThreadpoolIo
CloseThreadpoolIo
CreateThreadpoolIo
StartThreadpoolIo
WaitForThreadpoolIoCallbacks
Clean-up groupCloseThreadpoolCleanupGroup
CloseThreadpoolCleanupGroupMembers
CreateThreadpoolCleanupGroup
PoolCloseThreadpool
CreateThreadpool
SetThreadpoolThreadMaximum
SetThreadpoolThreadMinimum
Callback environmentDestroyThreadpoolEnvironment
InitializeThreadpoolEnvironment
SetThreadpoolCallbackCleanupGroup
SetThreadpoolCallbackLibrary
SetThreadpoolCallbackPool
SetThreadpoolCallbackRunsLong
CallbackCallbackMayRunLong
Callback clean upDisassociateCurrentThreadFromCallback
FreeLibraryWhenCallbackReturns
LeaveCriticalSectionWhenCallbackReturns
ReleaseMutexWhenCallbackReturns
ReleaseSemaphoreWhenCallbackReturns
SetEventWhenCallbackReturns
 看到了吗?太惊喜了,一下子就出了这么多,我都吃惊微软这次看来是在线程池的改进方面下了大力气了。我越来越喜欢微软了,只是俺的机器还是试验不了这些函数。 这里我只能假设一个例子来简单讲解下可能的应用。 首先我们依然要编写自己的线程函数,或者叫线程体,这个函数即使打死你,微软也没法帮你提前做到Windows里^_^。自己动手写吧,你要注意不要死锁,不要运行时间太长,不要耗费太多资源,不要太低效率,等等,因为线程池好不好,效率高不高全看你的这个线程函数编写的如何。看到微软是如何快速的把关于性能问题的责任推到你的身上了吧? 接下来你就要创建自己的线程池,并且拿到一个像句柄一样的东西,但是它有个奇怪的名字PTP_POOL,也许是微软为了起一个与众不同的名字,以便把像我这样Windows开发老人给直接变成Windows开发废人吧?还好我识破了微软的伎俩,不然我就真的不知道该怎么用这个新的线程池了。要迷惑我这个老家伙,可没那么容易!ok,你要做的就是调用那个望名知意的CreateThreadpool,哈哈哈,看到了吗,那个pool的P居然是小写,又想迷惑我,并且它的唯一一个参数居然是保留不用的,必须传递NULL。据我所知现在Windows中很多的有保留参数的函数还从来没有将这些参数用起来过,创建池子的代码看起来象下面这样: PTP_POOL pool = CreateThreadpool(NULL); 看见那个难看而且奇怪的返回值类型了吧?PTP=Pointer to Thread Pool?还有中间那个多余且难看的下划线,再加上多余的POOL结尾,呵呵,我估计编写Windows这部分升级代码的老程序员没几个了,肯定用的都是新人,才会起一些这么不符合Windows传统的类型名称。     ok,有了池子,还要有一个优雅的环境才行,不然水质污染,等下放进去的线程函数小鱼就有可能都牺牲了,注意一般环境的初始化,应当在创建池子之前,当然没有池子你就没有地方放那些小鱼鱼,初始化环境象下面这样: TP_CALLBACK_ENVIRON CallBackEnviron; InitializeThreadpoolEnvironment(&CallBackEnviron); 这样这个环境也就初始化好了。 接下来我们需要做的就是指定我们刚挖好的池子里可以最少养多少鱼(多少线程),最多养多少鱼,通常呢,我们需要根据系统中CPU的数量,以及鱼的类型,来策略性的计算出这个最大数量。通常我喜欢指定是CPU数的两倍,象下面这样就可以指定池子中的最大和最小线程数量: SetThreadpoolThreadMaximum(pool, 1*2); //我只有一颗CPU L SetThreadpoolThreadMinimum(pool, 1); 到这里似乎好像我们已经准备好一且了,剩下的就是放养鱼苗(线程池线程函数)了,别急,等等,你好像忘记了什么,对了我们还缺少排污系统,虽然有了优雅的环境,但是没有排污系统,那么池子一样会变得一团糟。好的,好的,我们这就给这个池子订购并安装上排污系统,这个代码看起来象下面这样: PTP_CLEANUP_GROUP cleanupgroup =  CreateThreadpoolCleanupGroup(); 这样你就订购到了你需要的排污系统,看到了吗这些不需要你花一分钱,而是由Windows系统免费为你提供的,你需要的就是抓到这些东西的把柄(句柄HANDLE或者等价物指针等),但是有一点,虽然是免费的,但这和系统借给你的是差不多的,用完了你要归还给系统,不然,Windows就会立马把你的硬件资源消耗完,并且变得脾气暴躁,或者直接不再搭理你(死机)。为了避免这个脾气暴躁的家伙变得不合作,你最好把借它的东西最终还给它。后面我们会说如何把这些东西还给Windows。现在你借到了环境、借到了池子、借到了清污系统,那么就需要把这些东西接在一起,好让它们组成一个看起来象回事的池子,代码看起来象下面这样: SetThreadpoolCallbackPool(&CallBackEnviron, pool); SetThreadpoolCallbackCleanupGroup(&CallBackEnviron,cleanupgroup, NULL); 现在我们需要把我们买来的普通鱼卵(自定义的线程池线程函数),它可能就是小草鱼的卵,首先要做的就是孵化,看起来像下面这样: PTP_WORK work = CreateThreadpoolWork( (PTP_WORK_CALLBACK) MyWorkCallback,                   NULL,                   &CallBackEnviron); 如果孵化不成功,那么小鱼就不会有个尾巴(work),它就会是空(NULL),而那个鱼卵MyWorkCallback则是你自己从C/C++市场上买来的鱼卵,当然通常是你自己DIY出来的,鱼卵很重要,如果不好那么就很可能无法孵化(CreateThreadpoolWork),草鱼孵化出来后,我们就要把它放养到池子里,这要通过下面的过程来实现: SubmitThreadpoolWork(work); 至此我们成功地将鱼(线程池线程函数)成功的放养到了,线程池中,在鱼长大需要捞起并结束放养后,我们不要忘记把这些养鱼设备还给那个脾气古怪的Windows,通过下面来做到这个: //拆解排污系统与池子的连接  CloseThreadpoolCleanupGroupMembers(cleanupgroup,                                        FALSE,                                        NULL); //关闭与归还排污系统 CloseThreadpoolCleanupGroup(cleanupgroup); //把池子也还给系统 CloseThreadpool(pool); 这样一个完整的养鱼(创建-运行-结束)周期就全部都有了,当然我们池子中还可以放养其它种的鱼类,比如: //1、孵化 PTP_TIMER timer = CreateThreadpoolTimer( (PTP_TIMER_CALLBACK) MyTimerCallback,                   NULL,                   &CallBackEnviron); //2、设定鱼的喂养时间 FILETIME FileDueTime; ULARGE_INTEGER ulDueTime; ulDueTime.QuadPart = (LONGLONG) -(1 * 10 * 1000 * 1000); FileDueTime.dwHighDateTime = ulDueTime.HighPart; FileDueTime.dwLowDateTime  = ulDueTime.LowPart; //3、放养 SetThreadpoolTimer(timer,                        &FileDueTime,                        0,                        0); 这看起来更像是一条锦鲤鱼。 至此我的Windows 2008 Server 线程池算是介绍完了吧,也不知道这样行不行,我没试过,代码全部是参考MSDN中的,微软不会因为这个而起诉我吧?我想他们更应该付给我稿费,我可是第一个帮他们宣传新线程池的人。J
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: