zoukankan      html  css  js  c++  java
  • 使用VC实现一个“智能”自增减线程池

    使用VC实现一个“智能”自增减线程池

     工作中接手了一款产品的改造。因为该产品可能使用很多线程,所以产品中使用了线程池。

     工程下载地址:DeInCreaseThreadPool

    转载自:http://blog.csdn.net/breaksoftware/article/details/7096657

            线程池的一个优点是降低线程创建和销毁的频率;缺点是可能在比较闲的时候还存在一定数量的空闲线程。这个也可以比作现实生活中的武器,对于一款武器,有其攻击的能力和防御的能力。有些设计可能会将攻击力做的很强但是防御力有所折扣,有些可能防御做的很好但是攻击力不足。于是如果将这些设计放在一起可能就很难比较个好坏来,但是可能很容易比较出一个“哪个更适合哪种战场”。

            于是,回到我们的产品。这款产品原始的线程池一开始时便创建了上百个休眠线程,可以说火力十足啊。但是我们评估后,我们认为大部分场景这些线程可能一辈子都在睡眠!这样的设计在我们预估的场景中明显是“不适宜”的。于是我接到一个任务就是改造之。让其成为一个根据需求可以自增减的线程池。

           对于自增减,这便是种策略,又回到攻击力和防御力的博弈上来。还是那句话:适合的才是好的。可以想象,如果自增减的频率过快,那干嘛使用线程池呢?如果过慢,那么干嘛自增减呢?我们的场景:线程池中的任务的增速不会快,减数可能快。目前我写的demo版中,我初始时建立了10个线程,当空闲线程等于1个时,我就会尝试再新建10个线程,当增加到30个线程时,就不增加线程了,任务会保留在列表中,待有空闲线程时去执行。当空闲线程数大于等于当前线程数一半时,我就会查看如果释放了10个线程,空闲线程是否小于等于我设置的最低空闲线程数,如果是,则不释放,否则就释放。当然这只是大致的逻辑。

    1. m_ThreadPool.Create( 30, 10, 10, 1 ); //最大线程数 最低线程数 递变数 最低空闲线程数  

           在demo中,我使用MFC写了个例子(Console版懒得写了)。其中DICThreadPool.h和DICThreadPool.cpp是线程池的相关实现,DICTaskObject.h中是任务要继承的基类。WorkerThread.h和WorkerThread.cpp是任务的实现,这个代码根据不同的业务改变而改变(你可定制),它中包含的类CWorkerThread要继承DICTaskObject.h中的CDICTaskObject,并实现基类中的几个虚函数。

    DICTaskObject.h

    1. enum EThreadRoutineExitType  
    2. {  
    3.     WAITEVENTOK = 0,  
    4.     OTHERRESON = 1  
    5. };  
    6.   
    7. class CDICTaskObject  
    8. {  
    9. public:  
    10.     CDICTaskObject(){};  
    11.     virtual ~CDICTaskObject(){};  
    12. public:  
    13.     virtual EThreadRoutineExitType Run() = 0;  
    14.     virtual BOOL AutoDelete() = 0;  
    15.     HANDLE m_hStopEvent;  
    16. };  

    WorkerThread.h

    1. class CWorkerThread:   
    2.     public CDICTaskObject  
    3. {  
    4. public:  
    5.     CWorkerThread();  
    6.     ~CWorkerThread();  
    7.   
    8. public:  
    9.     VOID SetAutoDelete( BOOL bAutoDel );  
    10.   
    11.     // 以下增加你的成员函数  
    12.       
    13. protected:  
    14.     EThreadRoutineExitType Run();  
    15.     BOOL AutoDelete();  
    16.   
    17. private:  
    18.     // 以下增加你的成员函数  
    19.       
    20. private:  
    21.     BOOL m_bAutoDelete;  
    22.   
    23.     // 以下增加你的成员变量  
    24.    
    25. };  

    这个类的实例一半都是new出来的,但是往往因为时机的问题,只有在相关操作执行后才可以delete掉它。于是线程池便提供了一个功能就是负责delete掉这个实例,要想让线程池去delete,就要调用SetAutoDelete(TRUE)。

    1. CWorkerThread* pWorkerThread = new CWorkerThread;  
    2.   
    3. pWorkerThread->SetAutoDelete( TRUE );  

    线程池创建后,要让线程池去执行这个任务,就可以

    1. m_ThreadPool.Run( pWorkerThread );  

    剩下的事就交给线程池去做吧。

    再说一下线程池模型。

    可以看见线程池做的事情还是很简单的。它只是负责保存任务、唤醒线程和新建一批新线程。

    线程的职责就是取任务执行任务,并判断是否需要减少线程数(带有一定的管理职责,让管理行为由一些行为触发可能比定时去检测要智能些)。

    MFC那个例子

    先创建线程池,然后新建任务,我会在屏幕中弹出一些窗口,这些窗口的存在周期由右侧的执行时间来决定。

    如果想查看详细信息,可以在debugview中设置过滤:

    然后我们可以查看刚才的日志

    日志中

    [plain] view plaincopy
    1. DeInCreaseThreadPool:Create thread 12508 and suspend it  
    2. DeInCreaseThreadPool:Create thread 10548 and suspend it  
    3. DeInCreaseThreadPool:Create thread 10648 and suspend it  
    4. DeInCreaseThreadPool:Create thread 10812 and suspend it  
    5. DeInCreaseThreadPool:Create thread 6336 and suspend it  
    6. DeInCreaseThreadPool:Create thread 10544 and suspend it  
    7. DeInCreaseThreadPool:Create thread 11712 and suspend it  
    8. DeInCreaseThreadPool:Create thread 8904 and suspend it  
    9. DeInCreaseThreadPool:Create thread 3388 and suspend it  
    10. DeInCreaseThreadPool:Create thread 7824 and suspend it  
    11. DeInCreaseThreadPool:Resume thread 3388  
    12. DeInCreaseThreadPool:Resume thread 6336  
    13. DeInCreaseThreadPool:Resume thread 7824  
    14. DeInCreaseThreadPool:Resume thread 8904  
    15. DeInCreaseThreadPool:Resume thread 10544  
    16. DeInCreaseThreadPool:Resume thread 10548  
    17. DeInCreaseThreadPool:Resume thread 10648  
    18. DeInCreaseThreadPool:Resume thread 10812  
    19. DeInCreaseThreadPool:Resume thread 11712  
    20. DeInCreaseThreadPool:Resume thread 12508  
    21. DeInCreaseThreadPool:Create 10 Threads  

    是初始创建线程池(最低10个,Create中设置的)

    [plain] view plaincopy
    1. DeInCreaseThreadPool:Inset a low priority task in the list  
    2. DeInCreaseThreadPool:ThreadPool is not Full,the task is being excuted in thread 3388  
    3. DeInCreaseThreadPool:Get a task from the list  

    这段是插入一个任务,然后3388号线程负责了这个任务

    [plain] view plaincopy
    1. DeInCreaseThreadPool:Inset a low priority task in the list  
    2. DeInCreaseThreadPool:There is 1 free threads,but the min count of free threads is 1,so I will create more threads  
    3. DeInCreaseThreadPool:Create thread 3176 and suspend it  
    4. DeInCreaseThreadPool:Create thread 12192 and suspend it  
    5. DeInCreaseThreadPool:Create thread 8596 and suspend it  
    6. DeInCreaseThreadPool:Create thread 7628 and suspend it  
    7. DeInCreaseThreadPool:Create thread 10612 and suspend it  
    8. DeInCreaseThreadPool:Create thread 10060 and suspend it  
    9. DeInCreaseThreadPool:Create thread 1692 and suspend it  
    10. DeInCreaseThreadPool:Create thread 12400 and suspend it  
    11. DeInCreaseThreadPool:Create thread 7436 and suspend it  
    12. DeInCreaseThreadPool:Create thread 8272 and suspend it  
    13. DeInCreaseThreadPool:Resume thread 1692  
    14. DeInCreaseThreadPool:Resume thread 3176  
    15. DeInCreaseThreadPool:Resume thread 7436  
    16. DeInCreaseThreadPool:Resume thread 7628  
    17. DeInCreaseThreadPool:Resume thread 8272  
    18. DeInCreaseThreadPool:Resume thread 8596  
    19. DeInCreaseThreadPool:Resume thread 10060  
    20. DeInCreaseThreadPool:Resume thread 10612  
    21. DeInCreaseThreadPool:Resume thread 12192  
    22. DeInCreaseThreadPool:Resume thread 12400  

    这段是因为刚开始的10个线程中只剩下1个空闲线程了,等于我们设置的最低空闲线程,于是就会再创建10个线程

    [plain] view plaincopy
    1. DeInCreaseThreadPool:Inset a low priority task in the list  
    2. DeInCreaseThreadPool:There is 1 free threads,but the min count of free threads is 1,so I will create more threads  
    3. DeInCreaseThreadPool:There is 30 threads,but the max count of threads is 30,so I can't create 10 threads  
    4. DeInCreaseThreadPool:ThreadPool is not Full,the task is being excuted in thread 13728  
    5. DeInCreaseThreadPool:Get a task from the list  
    6. DeInCreaseThreadPool:Inset a low priority task in the list  
    7. DeInCreaseThreadPool:There is 0 free threads,but the min count of free threads is 1,so I will create more threads  
    8. DeInCreaseThreadPool:There is 30 threads,but the max count of threads is 30,so I can't create 10 threads  
    9. DeInCreaseThreadPool:Get a task from the list  
    10. DeInCreaseThreadPool:ThreadPool is not Full,the task is being excuted in thread 13808  
    11. DeInCreaseThreadPool:Inset a low priority task in the list  
    12. DeInCreaseThreadPool:There is 0 free threads,but the min count of free threads is 1,so I will create more threads  
    13. DeInCreaseThreadPool:There is 30 threads,but the max count of threads is 30,so I can't create 10 threads  
    14. DeInCreaseThreadPool:ThreadPool is Full,the task is waiting for a free thread to excute  

    这是不断有新任务被插入到任务列表中,而线程池满了的情况。

    [plain] view plaincopy
    1. DeInCreaseThreadPool:There is 16 working threads,more than half of the count(30) of threads,I will not decrease the size of the thread pool  
    2. DeInCreaseThreadPool:Task of _ThreadProc 9028 is completed,delete the object of the task  
    3. DeInCreaseThreadPool:There is 15 working threads,more than half of the count(30) of threads,I will attempt to decrease the size of the thread pool  
    4. DeInCreaseThreadPool:I will decrease the thread pool by 10  
    5. DeInCreaseThreadPool:_ThreadProc 4612 Exit 1  
    6. DeInCreaseThreadPool:_ThreadProc 5132 Exit 1  
    7. DeInCreaseThreadPool:_ThreadProc 5240 Exit 1  
    8. DeInCreaseThreadPool:_ThreadProc 6608 Exit 1  
    9. DeInCreaseThreadPool:_ThreadProc 7628 Exit 1  
    10. DeInCreaseThreadPool:_ThreadProc 7720 Exit 1  
    11. DeInCreaseThreadPool:_ThreadProc 7724 Exit 1  
    12. DeInCreaseThreadPool:_ThreadProc 8224 Exit 1  
    13. DeInCreaseThreadPool:_ThreadProc 8272 Exit 1  
    14. DeInCreaseThreadPool:_ThreadProc 8496 Exit 1  

    这是一些任务完成了,空闲线程达到了当前线程一半了,就释放掉10个线程(Create中设置的递变线程数)。

    [plain] view plaincopy
    1. DeInCreaseThreadPool:The Count of Current Threads is 20.  
    2. DeInCreaseThreadPool:The Count of Current Working Threads is 9.  
    3. DeInCreaseThreadPool:The Count of Need Free Threads is 10.  
    4. DeInCreaseThreadPool:The Count of Min Free Threads is 1.  
    5. DeInCreaseThreadPool:If I decrease thread pool size,the count of free threads is less than min free count.I will not decrease the size of thread pool  
    6. DeInCreaseThreadPool:Task of _ThreadProc 11696 is completed,delete the object of the task  
    7. DeInCreaseThreadPool:There is 8 working threads,more than half of the count(20) of threads,I will attempt to decrease the size of the thread pool  
    8. DeInCreaseThreadPool:I will decrease the thread pool by 10  
    9. DeInCreaseThreadPool:_ThreadProc 7700 Exit 1  
    10. DeInCreaseThreadPool:_ThreadProc 7708 Exit 1  
    11. DeInCreaseThreadPool:_ThreadProc 8596 Exit 1  
    12. DeInCreaseThreadPool:_ThreadProc 8616 Exit 1  
    13. DeInCreaseThreadPool:_ThreadProc 8740 Exit 1  
    14. DeInCreaseThreadPool:_ThreadProc 9028 Exit 1  
    15. DeInCreaseThreadPool:_ThreadProc 9476 Exit 1  
    16. DeInCreaseThreadPool:_ThreadProc 10004 Exit 1  
    17. DeInCreaseThreadPool:_ThreadProc 10548 Exit 1  
    18. DeInCreaseThreadPool:_ThreadProc 10648 Exit 1  

    这是在递减到接近最低线程数的场景。

  • 相关阅读:
    Java实现 LeetCode 69 x的平方根
    Java实现 LeetCode 68 文本左右对齐
    Java实现 LeetCode 68 文本左右对齐
    Java实现 LeetCode 68 文本左右对齐
    Java实现 LeetCode 67 二进制求和
    Java实现 LeetCode 67 二进制求和
    Java实现 LeetCode 67 二进制求和
    Java实现 LeetCode 66 加一
    Java实现 LeetCode 66 加一
    CxSkinButton按钮皮肤类
  • 原文地址:https://www.cnblogs.com/Dageking/p/2954710.html
Copyright © 2011-2022 走看看