Windows线程池

1、线程池介绍

Windows提供了一个线程池机制来简化线程的创建、销毁、管理。使用系统提供的线程池机制相当方便而且很有效率,我们仅需要关注于我们的回调函数即可。我们可以自己来实现线程池机制,但是与我们的简单模拟来比,系统提供的线程池有着更多的优点:首先,线程池中线程的数目是动态调整的,其次,线程池利用IO完成端口的特性,它可以限制并发运行的线程数目,默认情况下,将会限制为与CPU数目相关的合理数目,这可以减少线程之间频繁切换。线程池还会挑选最近执行过的线程再次投入执行,从而避免了不必要的线程切换。系统提供的线程池背后的隐藏着巨大的策略。

在线程池编程中,我们从来不需要自己调用CreateThread.系统会自动为我们的进程创建线程,并在规定的条件下让线程池中的线程调用我们的回调函数.此外,这个线程在处理完成一个客户请求后,它不会立刻被销毁,而是回到线程池,准备好处理队列中的任何其他工作项,线程池会不断地重复使用其中的线程,而不会频繁地创建销毁线程,对应用程序来说,这样可以显著地提升性能,因为创建和销毁线程会消耗大量的时间.当然,如果线程池检测到创建的另一个线程将能更好地为应用程序服务,那么它会这样做.如果线程池检测到它的线程数量已经供过于求,那么它会销毁其中一些线程。

当一个进程初始化的时候,它并没有任何与线程池的开销.但是,一旦调用了线程池相关函数,系统就会为进程相应的内核资源,其中的一些资源在进程终止之前都将一直存在.正如我们可以看到,使用线程池的开销取决于用法:系统会以进程的名义来分配线程,其他内核以及内部数据结构.因此我们不应该盲目地使用这些线程池函数,而是必须谨慎地考虑,这些函数能做什么,以及它们不能做什么.

2、线程池应用范围

下面是我总结的一些线程池应用范围,可能是不全面的:

  1. 需要大量的线程来完成任务,且完成任务的时间比较短。 WEB服务器完成网页请求这样的任务,使用线程池技术是非常合适的。因为单个任务小,而任务数量巨大,你可以想象一个热门网站的点击次数。 但对于长时间的任务,比如一个Telnet连接请求,线程池的优点就不明显了。因为Telnet会话时间比线程的创建时间大多了。
  2. 对性能要求苛刻的应用,比如要求服务器迅速相应客户请求。
  3. 接受突发性的大量请求,但不至于使服务器因此产生大量线程的应用。突发性大量客户请求,在没有线程池情况下,将产生大量线程,虽然理论上大部分操作系统线程数目最大值不是问题,短时间内产生大量线程可能使内存到达极限,并出现"OutOfMemory"的错误。

3、新旧线程池技术

新的线程池函数必须在Vista操作系统或以上实现,且 C++ 编译器版本至少是 VS2008;旧的线程池函数则可以在2000/XP下实现

Vista/2008/7(大多实现在用户态,效率更高):

            1:单步使用线程池:TrySubmitThreadpoolCallb ack 
            2:两步使用线程池:CreateThreadpoolWork/SubmitThreadpoolWork
                                等待工作完成:WaitForThreadpooWorkCall backs
                                清理:CloseThreadpoolWork。这样可以多次提交
            3:线程池定时器:CreateThreadpoolTimer/CloseThreadpoolTimer/
                              WaitForThreadpoolTimerCa llbacks
            4:I/O完成端口:CreateThreadpoolIo/IoCompletioCallback/
                            StartThreadpoolIo/CloseThreadpoolIo/
                            WaitForThreadpoolIoCallb acks
            5:注册等待:CreateThreadpoolWait/SetThreadpoolWait/
                          CloseThreadpoolWait/WaitForThreadPoolWaitCal lbacks
            6:线程池设置:InitializeThreadpoolEnvi roment/DestroyThreadpoolEnvirom ent
                            CreateThreadpool/SetThreadpoolCallbackPoo l/CloseThreadpool/
                            SetThreadpoolThreadMinim um/SetThreadpoolThreadMaxim um
                            CreateThreadpoolCleaupGr oup/SetThreadpoolCallbackCle anupGroup/
                            CloseThreadpoolCleanupGr oupMembers/CloseThreadpoolCleanupGr oup/
                            DisassociateCurrentThrea dFromCallback
                            CallbackMayRunLong/SetThreadpoolCallbackRun Log(提示线程可能会运行很久)
                            LeaveCriticalSectionWhen CallbackReturns/FreeLibraryWhenCallbackR eturns/
                            ReleaseMutexWhenCallback Returns/ReleaseSemaphoreWheCallb ackReturns/
                            SetEvetWheCallbackReturn s
2000/XP(大多实现在内核态,效率不高):
            1:使用线程池:QueueUserWorkItem
            2:定时器:CreateTimerQueue/CreateTimerQueueTimer/
                      ChangeTimerQueueTimer/DeleteTimerQueueTimer/DeleteTimerQueue
            3:I/O完成端口:BindIoCompletioCallback/FileIoCompletionRoutine
            4:注册等待:RegisterWaitForSingleObj ect/UnregisterWait(Ex)
CLR:
          1:线程池:ThreadPool.QueueUserWorkItem/UnsafeQueueUserWorkItem
          2:I/O完成端口:ThreadPool.BindHandle/UnsafeQueueNativeOverlapped(WCF使用了这个函数)
          3:定时器:System.Threadig.Timer
          4:注册等待:ThreadPool.RegisterWaitForSingleObject/UnsafeRegisterWaitForSingleObject
          5:线程管理:ThreadPool.SetMaxThreads/SetMinThreads
4、线程池的使用
线程池能够帮助我们做一下事情:

    ①:以异步的方式调用一个函数。

    ②:每隔一段时间调用一个函数。

    ③:当内核对象触发时调用一个函数。

    ④:当异步IO完成时调用一个函数。

①、 以异步的方式调用一个函数
即使用线程池中的一个线程来执行一个函数。
TrySubmitThreadpoolCallback():向线程池提交工作请求(一次性提交)。
CreateThreadpoolWork():为线程池创建一个提交工作的工作对象。
SubmitThreadpoolWork():向线程池提交工作请求(可以多次提交)。
WaitForThreadpoolWorkCallbacks():取消已提交但未执行的工作项/等待工作项处理完成而将自己挂起。
CloseThreadpoolWork():关闭可以多次提交工作的工作对象。

eg:
#include<Windows.h>
#include<iostream>
#include<cstdlib>

using namespace std;

VOID CALLBACK WorkCallback(PTP_CALLBACK_INSTANCE Instance,PVOID Context,PTP_WORK Work)
{
    cout<<"this is WorkCallback function!"<<endl;
}

void main()
{
    PTP_WORK tpWork;
    
    //创建工作对象
    tpWork = CreateThreadpoolWork(WorkCallback,NULL,NULL);

    //多次提交工作
    SubmitThreadpoolWork(tpWork);
    SubmitThreadpoolWork(tpWork);
	SubmitThreadpoolWork(tpWork);

    //等待工作结束
    WaitForThreadpoolWorkCallbacks(tpWork,false);

    //关闭工作对象
    CloseThreadpoolWork(tpWork);
    
    system("pause");
}
②、 每隔一段时间调用一个函数
  每隔一段时间异步(使用线程池中的一个线程)执行一个函数,使用CreateThreadpoolTimer()创建线程池定时器对象,设置执行的回调函数和传入参数,使用SetThreadpoolTimer()来设置开始时间和间隔时间。
 
③、当内核对象(互斥锁、信号量、事件对象、计时器、进程、线程等)触发时调用一个函数
即内核对象触发时异步(使用线程池中的一个线程)执行一个函数,CreateThreadpoolWait()函数用来创建线程池等待对象,设置回调函数和传入的参数,SetThreadpoolWait()函数将一个内核对象绑定到这个线程池等待对象。
RegisterWaitForSingleObject()函数也可以实现当指定的内核对象触发或等待时间超时时使用线程池中的一个线程执行一个函数。

④、当异步IO请求完成时调用一个函数
即当异步IO完成时异步(调用线程池中的一个线程函数)执行一个函数。CreateThreadpoolIo()函数用来创建一个线程池IO对象,并关联要读写的设备文件和设置I/O完成后的回调函数,每次发出异步I/O请求之前都要调用StartThreadpoolIo()函数,
如果不调用StartThreadpoolIo函数则不会调用回调函数。当不需要读写设备文件后调用CloseThreadpoolIo()解除设备文件与线程池IO对象的关系。

/*
剩余线程池处理的事情可参见:
            http://www.cnblogs.com/kzloser/archive/2013/03/11/2909221.html
                http://blog.csdn.net/ithzhang/article/details/8373243

转载出处:http://blog.csdn.net/augusdi/article/details/5683907

         http://www.ibm.com/developerworks/cn/java/l-threadPool/

         http://blog.sina.com.cn/s/blog_4673b4ff01011clk.html

         http://www.cnblogs.com/kzloser/archive/2013/03/11/2909221.html

         http://blog.csdn.net/ithzhang/article/details/8373243


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值