您的位置:首页 > 其它

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

2013-06-16 12:02 597 查看
工作中接手了一款产品的改造。因为该产品可能使用很多线程,所以产品中使用了线程池。(转载请指明来自BreakSoftware的CSDN博客)

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

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

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

[cpp]
view plaincopyprint?

m_ThreadPool.Create( 30, 10, 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

[cpp]
view plaincopyprint?

enum EThreadRoutineExitType { WAITEVENTOK = 0, OTHERRESON = 1 }; class CDICTaskObject { public: CDICTaskObject(){}; virtual ~CDICTaskObject(){}; public: virtual EThreadRoutineExitType Run() = 0; virtual BOOL AutoDelete() = 0; HANDLE m_hStopEvent; };

enum EThreadRoutineExitType
{
WAITEVENTOK = 0,
OTHERRESON = 1
};

class CDICTaskObject
{
public:
CDICTaskObject(){};
virtual ~CDICTaskObject(){};
public:
virtual EThreadRoutineExitType Run() = 0;
virtual BOOL AutoDelete() = 0;
HANDLE m_hStopEvent;
};


WorkerThread.h

[cpp]
view plaincopyprint?

class CWorkerThread: public CDICTaskObject { public: CWorkerThread(); ~CWorkerThread(); public: VOID SetAutoDelete( BOOL bAutoDel ); // 以下增加你的成员函数 protected: EThreadRoutineExitType Run(); BOOL AutoDelete(); private: // 以下增加你的成员函数 private: BOOL m_bAutoDelete; // 以下增加你的成员变量 };

class CWorkerThread:
public CDICTaskObject
{
public:
CWorkerThread();
~CWorkerThread();

public:
VOID SetAutoDelete( BOOL bAutoDel );

// 以下增加你的成员函数

protected:
EThreadRoutineExitType Run();
BOOL AutoDelete();

private:
// 以下增加你的成员函数

private:
BOOL m_bAutoDelete;

// 以下增加你的成员变量

};


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

[cpp]
view plaincopyprint?

CWorkerThread* pWorkerThread = new CWorkerThread;

pWorkerThread->SetAutoDelete( TRUE );

CWorkerThread* pWorkerThread = new CWorkerThread;

pWorkerThread->SetAutoDelete( TRUE );

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

[cpp]
view plaincopyprint?

m_ThreadPool.Run( pWorkerThread );

m_ThreadPool.Run( pWorkerThread );
剩下的事就交给线程池去做吧。

再说一下线程池模型。



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



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

MFC那个例子



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



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



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

日志中

[plain]
view plaincopyprint?

DeInCreaseThreadPool:Create thread 12508 and suspend it DeInCreaseThreadPool:Create thread 10548 and suspend it DeInCreaseThreadPool:Create thread 10648 and suspend it DeInCreaseThreadPool:Create thread 10812 and suspend it DeInCreaseThreadPool:Create thread 6336 and suspend it DeInCreaseThreadPool:Create thread 10544 and suspend it DeInCreaseThreadPool:Create thread 11712 and suspend it DeInCreaseThreadPool:Create thread 8904 and suspend it DeInCreaseThreadPool:Create thread 3388 and suspend it DeInCreaseThreadPool:Create thread 7824 and suspend it DeInCreaseThreadPool:Resume thread 3388 DeInCreaseThreadPool:Resume thread 6336 DeInCreaseThreadPool:Resume thread 7824 DeInCreaseThreadPool:Resume thread 8904 DeInCreaseThreadPool:Resume thread 10544 DeInCreaseThreadPool:Resume thread 10548 DeInCreaseThreadPool:Resume thread 10648 DeInCreaseThreadPool:Resume thread 10812 DeInCreaseThreadPool:Resume thread 11712 DeInCreaseThreadPool:Resume thread 12508 DeInCreaseThreadPool:Create 10 Threads
DeInCreaseThreadPool:Create thread 12508 and suspend it
DeInCreaseThreadPool:Create thread 10548 and suspend it
DeInCreaseThreadPool:Create thread 10648 and suspend it
DeInCreaseThreadPool:Create thread 10812 and suspend it
DeInCreaseThreadPool:Create thread 6336 and suspend it
DeInCreaseThreadPool:Create thread 10544 and suspend it
DeInCreaseThreadPool:Create thread 11712 and suspend it
DeInCreaseThreadPool:Create thread 8904 and suspend it
DeInCreaseThreadPool:Create thread 3388 and suspend it
DeInCreaseThreadPool:Create thread 7824 and suspend it
DeInCreaseThreadPool:Resume thread 3388
DeInCreaseThreadPool:Resume thread 6336
DeInCreaseThreadPool:Resume thread 7824
DeInCreaseThreadPool:Resume thread 8904
DeInCreaseThreadPool:Resume thread 10544
DeInCreaseThreadPool:Resume thread 10548
DeInCreaseThreadPool:Resume thread 10648
DeInCreaseThreadPool:Resume thread 10812
DeInCreaseThreadPool:Resume thread 11712
DeInCreaseThreadPool:Resume thread 12508
DeInCreaseThreadPool:Create 10 Threads
是初始创建线程池(最低10个,Create中设置的)

[plain]
view plaincopyprint?

DeInCreaseThreadPool:Inset a low priority task in the list DeInCreaseThreadPool:ThreadPool is not Full,the task is being excuted in thread 3388 DeInCreaseThreadPool:Get a task from the list
DeInCreaseThreadPool:Inset a low priority task in the list
DeInCreaseThreadPool:ThreadPool is not Full,the task is being excuted in thread 3388
DeInCreaseThreadPool:Get a task from the list
这段是插入一个任务,然后3388号线程负责了这个任务

[plain]
view plaincopyprint?

DeInCreaseThreadPool:Inset a low priority task in the list DeInCreaseThreadPool:There is 1 free threads,but the min count of free threads is 1,so I will create more threads DeInCreaseThreadPool:Create thread 3176 and suspend it DeInCreaseThreadPool:Create thread 12192 and suspend it DeInCreaseThreadPool:Create thread 8596 and suspend it DeInCreaseThreadPool:Create thread 7628 and suspend it DeInCreaseThreadPool:Create thread 10612 and suspend it DeInCreaseThreadPool:Create thread 10060 and suspend it DeInCreaseThreadPool:Create thread 1692 and suspend it DeInCreaseThreadPool:Create thread 12400 and suspend it DeInCreaseThreadPool:Create thread 7436 and suspend it DeInCreaseThreadPool:Create thread 8272 and suspend it DeInCreaseThreadPool:Resume thread 1692 DeInCreaseThreadPool:Resume thread 3176 DeInCreaseThreadPool:Resume thread 7436 DeInCreaseThreadPool:Resume thread 7628 DeInCreaseThreadPool:Resume thread 8272 DeInCreaseThreadPool:Resume thread 8596 DeInCreaseThreadPool:Resume thread 10060 DeInCreaseThreadPool:Resume thread 10612 DeInCreaseThreadPool:Resume thread 12192 DeInCreaseThreadPool:Resume thread 12400
DeInCreaseThreadPool:Inset a low priority task in the list
DeInCreaseThreadPool:There is 1 free threads,but the min count of free threads is 1,so I will create more threads
DeInCreaseThreadPool:Create thread 3176 and suspend it
DeInCreaseThreadPool:Create thread 12192 and suspend it
DeInCreaseThreadPool:Create thread 8596 and suspend it
DeInCreaseThreadPool:Create thread 7628 and suspend it
DeInCreaseThreadPool:Create thread 10612 and suspend it
DeInCreaseThreadPool:Create thread 10060 and suspend it
DeInCreaseThreadPool:Create thread 1692 and suspend it
DeInCreaseThreadPool:Create thread 12400 and suspend it
DeInCreaseThreadPool:Create thread 7436 and suspend it
DeInCreaseThreadPool:Create thread 8272 and suspend it
DeInCreaseThreadPool:Resume thread 1692
DeInCreaseThreadPool:Resume thread 3176
DeInCreaseThreadPool:Resume thread 7436
DeInCreaseThreadPool:Resume thread 7628
DeInCreaseThreadPool:Resume thread 8272
DeInCreaseThreadPool:Resume thread 8596
DeInCreaseThreadPool:Resume thread 10060
DeInCreaseThreadPool:Resume thread 10612
DeInCreaseThreadPool:Resume thread 12192
DeInCreaseThreadPool:Resume thread 12400
这段是因为刚开始的10个线程中只剩下1个空闲线程了,等于我们设置的最低空闲线程,于是就会再创建10个线程

[plain]
view plaincopyprint?

DeInCreaseThreadPool:Inset a low priority task in the list DeInCreaseThreadPool:There is 1 free threads,but the min count of free threads is 1,so I will create more threads DeInCreaseThreadPool:There is 30 threads,but the max count of threads is 30,so I can't create 10 threads DeInCreaseThreadPool:ThreadPool is not Full,the task is being excuted in thread 13728 DeInCreaseThreadPool:Get a task from the list DeInCreaseThreadPool:Inset a low priority task in the list DeInCreaseThreadPool:There is 0 free threads,but the min count of free threads is 1,so I will create more threads DeInCreaseThreadPool:There is 30 threads,but the max count of threads is 30,so I can't create 10 threads DeInCreaseThreadPool:Get a task from the list DeInCreaseThreadPool:ThreadPool is not Full,the task is being excuted in thread 13808 DeInCreaseThreadPool:Inset a low priority task in the list DeInCreaseThreadPool:There is 0 free threads,but the min count of free threads is 1,so I will create more threads DeInCreaseThreadPool:There is 30 threads,but the max count of threads is 30,so I can't create 10 threads DeInCreaseThreadPool:ThreadPool is Full,the task is waiting for a free thread to excute
DeInCreaseThreadPool:Inset a low priority task in the list
DeInCreaseThreadPool:There is 1 free threads,but the min count of free threads is 1,so I will create more threads
DeInCreaseThreadPool:There is 30 threads,but the max count of threads is 30,so I can't create 10 threads
DeInCreaseThreadPool:ThreadPool is not Full,the task is being excuted in thread 13728
DeInCreaseThreadPool:Get a task from the list
DeInCreaseThreadPool:Inset a low priority task in the list
DeInCreaseThreadPool:There is 0 free threads,but the min count of free threads is 1,so I will create more threads
DeInCreaseThreadPool:There is 30 threads,but the max count of threads is 30,so I can't create 10 threads
DeInCreaseThreadPool:Get a task from the list
DeInCreaseThreadPool:ThreadPool is not Full,the task is being excuted in thread 13808
DeInCreaseThreadPool:Inset a low priority task in the list
DeInCreaseThreadPool:There is 0 free threads,but the min count of free threads is 1,so I will create more threads
DeInCreaseThreadPool:There is 30 threads,but the max count of threads is 30,so I can't create 10 threads
DeInCreaseThreadPool:ThreadPool is Full,the task is waiting for a free thread to excute
这是不断有新任务被插入到任务列表中,而线程池满了的情况。

[plain]
view plaincopyprint?

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 DeInCreaseThreadPool:Task of _ThreadProc 9028 is completed,delete the object of the task 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 DeInCreaseThreadPool:I will decrease the thread pool by 10 DeInCreaseThreadPool:_ThreadProc 4612 Exit 1 DeInCreaseThreadPool:_ThreadProc 5132 Exit 1 DeInCreaseThreadPool:_ThreadProc 5240 Exit 1 DeInCreaseThreadPool:_ThreadProc 6608 Exit 1 DeInCreaseThreadPool:_ThreadProc 7628 Exit 1 DeInCreaseThreadPool:_ThreadProc 7720 Exit 1 DeInCreaseThreadPool:_ThreadProc 7724 Exit 1 DeInCreaseThreadPool:_ThreadProc 8224 Exit 1 DeInCreaseThreadPool:_ThreadProc 8272 Exit 1 DeInCreaseThreadPool:_ThreadProc 8496 Exit 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
DeInCreaseThreadPool:Task of _ThreadProc 9028 is completed,delete the object of the task
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
DeInCreaseThreadPool:I will decrease the thread pool by 10
DeInCreaseThreadPool:_ThreadProc 4612 Exit 1
DeInCreaseThreadPool:_ThreadProc 5132 Exit 1
DeInCreaseThreadPool:_ThreadProc 5240 Exit 1
DeInCreaseThreadPool:_ThreadProc 6608 Exit 1
DeInCreaseThreadPool:_ThreadProc 7628 Exit 1
DeInCreaseThreadPool:_ThreadProc 7720 Exit 1
DeInCreaseThreadPool:_ThreadProc 7724 Exit 1
DeInCreaseThreadPool:_ThreadProc 8224 Exit 1
DeInCreaseThreadPool:_ThreadProc 8272 Exit 1
DeInCreaseThreadPool:_ThreadProc 8496 Exit 1
这是一些任务完成了,空闲线程达到了当前线程一半了,就释放掉10个线程(Create中设置的递变线程数)。

[plain]
view plaincopyprint?

DeInCreaseThreadPool:The Count of Current Threads is 20. DeInCreaseThreadPool:The Count of Current Working Threads is 9. DeInCreaseThreadPool:The Count of Need Free Threads is 10. DeInCreaseThreadPool:The Count of Min Free Threads is 1. 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 DeInCreaseThreadPool:Task of _ThreadProc 11696 is completed,delete the object of the task 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 DeInCreaseThreadPool:I will decrease the thread pool by 10 DeInCreaseThreadPool:_ThreadProc 7700 Exit 1 DeInCreaseThreadPool:_ThreadProc 7708 Exit 1 DeInCreaseThreadPool:_ThreadProc 8596 Exit 1 DeInCreaseThreadPool:_ThreadProc 8616 Exit 1 DeInCreaseThreadPool:_ThreadProc 8740 Exit 1 DeInCreaseThreadPool:_ThreadProc 9028 Exit 1 DeInCreaseThreadPool:_ThreadProc 9476 Exit 1 DeInCreaseThreadPool:_ThreadProc 10004 Exit 1 DeInCreaseThreadPool:_ThreadProc 10548 Exit 1 DeInCreaseThreadPool:_ThreadProc 10648 Exit 1
DeInCreaseThreadPool:The Count of Current Threads is 20.
DeInCreaseThreadPool:The Count of Current Working Threads is 9.
DeInCreaseThreadPool:The Count of Need Free Threads is 10.
DeInCreaseThreadPool:The Count of Min Free Threads is 1.
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
DeInCreaseThreadPool:Task of _ThreadProc 11696 is completed,delete the object of the task
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
DeInCreaseThreadPool:I will decrease the thread pool by 10
DeInCreaseThreadPool:_ThreadProc 7700 Exit 1
DeInCreaseThreadPool:_ThreadProc 7708 Exit 1
DeInCreaseThreadPool:_ThreadProc 8596 Exit 1
DeInCreaseThreadPool:_ThreadProc 8616 Exit 1
DeInCreaseThreadPool:_ThreadProc 8740 Exit 1
DeInCreaseThreadPool:_ThreadProc 9028 Exit 1
DeInCreaseThreadPool:_ThreadProc 9476 Exit 1
DeInCreaseThreadPool:_ThreadProc 10004 Exit 1
DeInCreaseThreadPool:_ThreadProc 10548 Exit 1
DeInCreaseThreadPool:_ThreadProc 10648 Exit 1
这是在递减到接近最低线程数的场景。

以下是该工程地址

DeInCreaseThreadPool

(转载请指明出处)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: