A Method of Worker Thread Pooling






3.63/5 (20 votes)
Feb 6, 2003
6 min read

147694

4238
A Method of Worker Thread Pooling
Introduction
In many of our applications we use multi threading for better performance. Most of us already knows and using multi threading applications. And we know that thread creation is a resource intensive job. It is always better to reuse the threads, and most of us do this also. This article talks about such a thread pooling (worker thread) architecture. It will be great if you can provide let me know about any bugs that are found and any improvements that can be done to this.
Architecture in brief
The main architecture of the thread pool is given below in the class diagram.
As you can see in the above class diagram the application has mainly three classes, they are
-
CThPool
class : This is the main thread pool class. To use thread pool you have to only create an instance of this class. -
CThread
class : This class encapsulates one thread. You don't have to create any instance of this class. TheCThPool
class will return aCThread
class, which you should use. You should not also destroy theCThread
object that you received from theCThPool
class instance. -
CThTarget
: This is the base class of all the target objects which can be passed to theCThread
class as target. This is an abstract class withrun()
as the pure virtual method. You should implement therun()
in your inherited class. As shown in the class diagram for the classCYourClass
.
Using the code
To use the thread pool code we have to do the following
- Create an instance of the pool. Refer the sample code below.
CThpool *m_pThPool; m_pThPool = new CThPool();
- Change the maximum pool size if you want to change the maximum number of
threads that can be created for use at any instance of time for your system. By
default this is 5. You can also change the pool size at run time for better
performance as you require.
m_pThPool->setMaxPoolSize(10); //You can pass any integer value.
- Create a class as shown in the class diagram, which will inherit the
CThTarget
class and implement the pure virtual functionvoid
run
(). Refer the sample code belowclass CThTargetSuper : public CThTarget { public: CThTargetSuper(); virtual ~CThTargetSuper(); void run(); } //------------------------------ void CThTargetSuper::run() { //Write your code here to do some process }
- Create an instance of your class, which you have defined as above
CThTargetSuper* pTarget = new CThTargetSuper();
- When you need to use a thread to do some process which is defined on the
run()
function of your class. Then get an instance ofCThread
class from the pool by calling the functiongetThread()
. Then call thesetTarget()
function of theCThread
instance you received and pass the reference of your inheritedCThTarget
class.CThread * pTh=NULL; pTh = m_pThPool->getThread(); //m_pThPool is an instance of CThPool if( pTh!=NULL) pTh->setTarget(pTarget);
Note : As you see in the above code the
CThread
instance received from theCThPool::getThread()
function may returnNULL
. This is in case of all the threads are busy and no free thread is available and the pool's current size is already achieved the Max pool size. If you want the job should be processed then you can try again after some time. The code can be modified as follows. But if this code is executed by the main GUI thread then the while loop may cause problem if the threads are busy for long time. In such cases this code should be executed in a different thread.CThread * pTh=NULL; pTh = m_pThPool->getThread(); //m_pThPool is an instance of CThPool while(pTh ==NULL) { Sleep(100); pTh = m_pThPool->getThread(); } if( pTh!=NULL) pTh->setTarget(pTarget);
- After
CThread::setTarget()
function call therun()
function of theCThTarget
type object will run in a separate thread. The thread will automatically return to the pool when therun()
function finishes.Note : Once the thread will be completed the
CThTarget
object cannot be used again. This is because once therun()
function finishes the thread deletes the instance of theCThTarget
. If you want to use theCThTarget
object later then you have to tell the thread explicitly by setting the auto delete flag ofCThTarget
toFALSE
as given in the code below.CThTargetSuper* pTarget = new CThTargetSuper(); pTarget->setAutoDelete(FALSE);
The default value is
TURE
. You can check this at any time by callingAutoDelete()
. It returnsTRUE
if the flag is set asTRUE
.Never call
setTarget()
again on the sameCThread
instance that you received from the lastgetThread()
object. Always usegetThread()
onCThPool
instance to get aCThread
object and then usesetTarget()
on that object only once.
Additional Features
How To Set Max Free Pool Size
Some times our application may need let 100 threads but most of the time the required thread is less than 20. In that case it is no need to create and keep 100 threads always in the pool. In such cases we can define the maximum free pool size to 20.This will make sure that not more than 20 idle threads will be available in the free pool. If required more number of threads will be created as on demand. Sample code is given below.
m_pThPool = new CThPool(); m_pThPool->setMaxPoolSize(100); //Maximum pool size m_pThPool->setMaxFreePoolSize(20); //Maximum free pool size
Getting Statistics
Some times we may require statistics to know at any instance of time how many threads are busy and how many threads are free, what is the pool size now, etc. etc. We can get such information by calling some methods of pool. In the sample application the statistics are also used. The functions that are available to get the statistical information are
int CThPool::getCurPoolSize() // returns the current pool size. int CThPool::getMaxPoolSize() // returns the maximum pool size. int CThPool::getMaxFreePoolSize() // returns the maximum free pool size. int CThPool::getFreePoolSize() // returns the number // of idle threads in the pool.
About The Demo Program
The demo program uses one thread pool. Initially the pool has started with
one thread. And the Max pool size is 5. And the maximum free thread size is 2.
In the demo program CThTargetSuper
is the class, which extends
CThTarget
and implement the run()
method. The run
method simply increments the progress bar after sleeping 100 ms till it reaches
the end. If more number of threads will be assigned then the progress bar will
move fast. The run()
methods ends when the progress bar reaches the
end of the bar. And the after that the instance of the
CThTargetSuper
gets deleted by the thread (As the Auto Delete flag
is TRUE
by default) and the threads returns to the free pool and
remains in suspended mode till another work get assigned. The thread may also
exit if the number of threads that are present in the free pool is more than the
maximum limit.
Executing the Demo Program
After you start the program first create the pool by clicking the CreatePool button. Then you can click on the AssignThread button to assign a new thread. You can not assign more threads than the Max Pool size. The current number of threads busy in the pool is displayed in the statistics along with the idle threads and max pool size. You can change the the maximum pool size by clicking the button "+" or "-" . (Upper limit is defined as 20). You can also change the maximum free pool size by clicking the corresponding "+" / "-" button. You can also press the Refresh button to refresh the statistics. The statistics also gets automatically updated around every 2 seconds.
To repeat the process click on the Reset button so that the
progress bar will be reset to initial position. And you can assign the threads
again to increase the progress bar's progress.