script>
This source code, please http://asp.6to23.com/vcprogram/source/sourcefile/linuxpool.rar download
Creation and use of universal thread pool under Linux
This article gives a universal thread pool framework that will perform high levels of abstraction with thread execution related tasks, making it independent of specific execution tasks. In addition, the thread pool has dynamic scalability, which automatically adjusts the number of threads in the thread pool based on the light weight of the execution task. At the end of the article, we give a simple sample program. Through this sample program, we will find how simple it is to execute multithreaded tasks through the thread pool frame.
Why do I need a thread pool?
Most web servers, including web servers, email servers, and database servers, etc., which must have a huge connection request within the unit time, but the processing time is relatively short.
The server model we used in the traditional multi-threading scheme is once accepted, that is, create a new thread and performs tasks by the thread. After the task is executed, the thread exits, which is the "instant creation, instant destruction" policy. Although the time to create a thread has been greatly shortened than the creation process, if the task submitted to the thread is short, and the number of execution is extremely frequent, the server will be in a constant creation thread, destroy the state of the thread.
We divide the thread execution processes in the traditional solution into three processes: T1, T2, T3.
T1: Thread creation time
T2: Thread execution time, synchronization of threads, etc.
T3: Thread destruction time
Then we can see that the proportion of the overhead of the thread itself is (T1 T3) / (T1 T2 T3). This may account for about 20% to 50% more than the expenditure time. If the task execution time is very frequent, this overhead will not be ignored.
In addition, the thread pool can reduce the number of threads created. Usually the concurrent thread allowed by the thread pool is uploaded. If the number of threads that need concurrently more than the upper bound, then a part of the thread will wait. In the traditional program, if the number of requests is 2000, the system may need to generate 2000 threads. Although this is not a big number, some machines may not reach this requirement.
Therefore, the emergence of thread pool is intended to reduce the overhead brought by the thread pool itself. The thread pool uses a pre-created technology. After the application starts, you will create a certain number of threads (N1) immediately, put them in the idle queue. These threads are in a suspended state, which does not consume the CPU, but occupy a smaller memory space. When the task arrives, the buffer pool selects an idle thread and incorporates the task to run in this thread. When N1 threads are processed tasks, the buffer pool automatically creates a certain number of new threads for more tasks. The thread does not exit after the task is executed, but continues to keep the next task in the pool. When the system is idle, most threads have been paused, and the thread pool automatically destroys a thread and reclaim system resources.
Based on this pre-creation technology, the thread pool puts the turnover of threads and destroy itself to the various specific tasks. The more executions, the smaller the thread itself shared by each task, but we will It may be necessary to consider the overhead of synchronization between the threads.
Build a threaded pool frame
General thread pools must have the following components:
Thread pool manager: used to create and manage thread pools
Working thread: thread actually implemented in the thread pool
Task Interface: Although most of the cases of the thread pool is used to support the web server, we abstract the task of threads to form a task interface, so that the thread pool is independent of the specific task. Task Quele: The concept of thread pool is specific to implementation may be a queue, a data structure such as a linked list, where the execution thread is saved.
Our universal thread pool frame consists of five important parts, CThreadManage, CthreadManage, Cthread, CJOB, CWORKERTHREAD, in addition to this framework, including thread synchronous class CThreadMutex and ccondition.
CJOB is a base class for all tasks that provides an interface run, all of which must be inherited from this class while implementing the RUN method. The specific task logic is realized in this method.
CThread is a wrapper in Linux, which encapsulates the most frequently used properties and methods of Linux threads. It is also an abstract class, which is the base class of all thread classes, with an interface RUN.
CWORKERTHREAD is a thread class that is actually scheduled and executed, which inherits from CTHREAD to implement the RUN method in CThread.
CThreadPool is a thread pool class that is responsible for saving threads, release threads, and scheduling threads.
CthreadManage is a direct interface of the thread pool and the user that shields the internal specific implementation.
CThreadMutex is used between the thread mutual exclusion.
Ccondition is the package of condition variables for synchronization between threads.
The inheritance relationship between their classes is shown in the following figure:
The timing of the thread pool is simple, as shown below. CthreadManage deals directly with the client, which accepts the initial number of threads that need to be created, and accepts the tasks submitted by the client. The task here is the specific non-abstract task. CTHREADMANAGE is actually called by CThreadPool. CThreadPool creates a specific thread and distributes the task submitted by the client to CWORKERTHREAD, CWORKERTHREAD actually performs a specific task.
Understanding system components
Below we are separated by understanding each component in the system.
CThreadManage
The function of CThreadManage is very simple, which provides the easiest way, and the class definition is as follows:
Class CThreadManage
{
Private:
Cthreadpool * m_pool;
INT m_NUMOFTHREAD;
protected:
PUBLIC:
Void setParalLnum (int Num);
CthreadManage ();
CThreadManage (int Num);
Virtual ~ cthreadmanage ();
Void Run (CJOB * JOB, VOID * JOBDATA);
Void TerminateAll (Void);
}
Where m_pool points to the actual thread pool; M_NumOfThread is the number of threads that allow for concurrency when the initial creation is created. In addition, Run and TerminateAll methods are also very simple, just simply call some of the relevant methods of CThreadPool. The specific implementation is as follows:
CthreadManage :: cthreadmanage () {
m_numofthread = 10;
m_pool = new cthreadpool (m_numofthread);
}
CthreadManage :: CthreadManage (int Num) {
m_numofthread = NUM;
m_pool = new cthreadpool (m_numofthread);
}
CthreadManage :: ~ cthreadManage () {ix (null! = M_pool)
Delete m_pool;
}
Void CthreadManage :: setParalLnum (int Num) {
m_numofthread = NUM;
}
Void CthreadManage :: Run (CJOB * Job, Void * JobData) {
m_pool-> run (job, jobdata);
}
Void CthreadManage :: TerminateAll (void) {
m_pool-> terminateAll ();
}
Cthread
The CTHREAD class implements a package in Linux, which is the base class of all threads, is also an abstract class, providing an abstract interface RUN, and all CTHREAD must implement the RUN method. The definition of CTHREAD is as follows:
Class CThread
{
Private:
Int m_ERRCODE;
Semaphore m_threadsemaphore; // the inner semaphore, which is buy to realize
Unsigned long m_threadid;
Bool m_detach; // the thread is detached
Bool m_createsuspended; // if susndAfter Creating
Char * m_threadname;
ThreadState m_threadstate; // the state of the thread
protected:
Void Sterrcode (int errcode) {m_ERRCODE = Errcode;}
Static void * threadfunction (void *);
PUBLIC:
Cthread ();
CThread (Bool CreateSuspended, Bool Detach);
Virtual ~ cthread ();
Virtual void Run (void) = 0;
Void setthreadState (threadState State) {m_threadstate = state;}
Bool Terminate (Void); // Terminate The Threa
Bool Start (Void); // Start to Execute The Thread
Void exit (void);
Bool Wakeup (Void);
ThreadState GetthreadState (void) {return m_threadstate;}
INT getLastError (void) {return m_ERRCODE;}
Void setthreadname (char * thrname) {structure (m_threadname, thrname);
Char * getthreadname (void) {return m_threadname;}
Int getthreadid (void) {return m_threadid;}
Bool setPriority (int priority);
INT getPriority (void);
INT getConcurrency (void);
Void setConcurrency (int Num);
Bool Detach (void);
Bool Join (void);
Bool Yield (void); int Self (void);
}
The state of the thread can be divided into four, idle, busy, suspend, termination (including normal exit and abnormal exit). Since the current Linux thread library does not support suspend operations, the suspend operation here is similar to a pause. If you don't want to perform a task immediately after the thread is created, then we can "pause", if you need to run, wake up. One thing to note is that once the thread began to perform the task, it will not be suspended, which will continue the task.
The related operations of thread classes are very simple. The execution portal of the thread starts from the start () function, which will call the function threadfunction, threadFunction, and then call the actual RUN function to perform the actual task.
CThreadPool
CThreadPool is a bearing container for threads, which can generally be implemented as stack, one-way queue or two-way queue. In our system we use STL Vector to save threads. The implementation code of CThreadPool is as follows:
Class CThreadPool
{
Friend Class CWORKERTHREAD;
Private:
Unsigned int m_maxnum; // the max thread number That CAN CREATE AT THEAD NUM That
Unsigned int m_availlow; // the min num of idle thread that sole key
Unsigned int m_availhigh; // the max num of idle thread what Kept At The Same Time
Unsigned int m_availnum; // The Normal Thread Num of idle Num
Unsigned int m_initnum; // Normal Thread Num
protected:
CWORKERTHREAD * GetIdLethread (Void);
Void appendtoidlelist (crewerthread * jobthread);
Void MoveTobusylist (CWORKERTHREAD * IDLETHREAD);
Void MoveToidleList (CWORKERTHREAD * BUSYTHREAD);
Void deleteidLethread (int Num);
Void CreateIDLethread (int Num);
PUBLIC:
Cthreadmutex m_busymutex; //en visit busy list, use m_busymutex to Lock and Unlock
Cthreadmutex m_idlemutex; //en visit idle list, use m_idlemutex to lock and unlock
Cthreadmutex M_Jobmutex; // when Visit Job List, Use M_Jobmutex to Lock and Unlock
CThreadMutex M_Varmutex;
Ccondition m_busycond; // m_busycond is buy to sync busy thread list
Ccondition m_idlecond; // m_idlecond is buy to sync idle thread list
Ccondition m_idlejobcond; // m_jobcond is buy to sync job list
Ccondition M_MaxNumCond;
Vector
Vector
Cthreadpool ();
CthreadPool (int initnum);
Virtual ~ cthreadpool ();
Void setMaxNum (int Maxnum) {m_maxnum = maxnum;}
INT getMaxNum (void) {RETURN M_MAXNUM;}
Void setAvaillownum (INT minnum) {m_availlow = minnum;
Int getAvaillownum (void) {return m_availlow;}
Void setAvailhighnum (int highnum) {m_availhigh = highnum;
Int getavailhighnum (void) {return m_availhigh;}
INT getActualavailnum (void) {Return M_availnum;}
INT getAllNum (void) {return m_threadlist.size ();
INT getBusynum (void) {return m_busylist.size ();
Void setinitnum (int initnum) {m_initnum = initnum;}
Int getinitnum (void) {return m_initnum;}
Void TerminateAll (Void);
Void Run (CJOB * JOB, VOID * JOBDATA);
}
CthreadPool :: CthreadPool ()
{
m_maxnum = 50;
m_availlow = 5;
m_initnum = m_availnum = 10;
m_availhigh = 20;
m_busylist.clear ();
m_idlelist.clear ();
For (int i = 0; i CWORKERTHREAD * THR = New CWORKERTHREAD (); Thr-> setthreadpool (this); AppendToidList (THR); Thr-> start (); } } CthreadPool :: CThreadPool (int initnum) { Assert (INITNUM> 0 &TNUM <= 30); m_maxnum = 30; m_availlow = initnum-10> 0? INITNUM-10: 3; m_initnum = m_availnum = initnum; m_availhigh = initnum 10; m_busylist.clear (); m_idlelist.clear (); For (int i = 0; i CWORKERTHREAD * THR = New CWORKERTHREAD (); AppendToidList (THR); Thr-> setthreadpool (this); Thr-> start (); // begin the thread, The Thread Wait For Job } } CthreadPool :: ~ cthreadpool () { TerminateAll (); } Void CthreadPool :: TerminateAll () { For (int i = 0; i CWORKERTHREAD * THR = m_threadlist [i]; THR-> JOIN (); } Return; } CWORKERTHREAD * CTHREADPOOL :: getIdleThread (void) { While (m_idlelist.size () == 0) m_idlecond.wait (); m_idlemutex.lock (); IF (m_idlelist.size ()> 0) { CWORKERTHREAD * THR = (CWORKERTHREAD *) m_idlelist.front (); Printf ("Get Idle Thread% D / N", thr-> getthreadId ()); m_idlemutex.unlock (); Return THR; } m_idlemutex.unlock (); Return NULL; } // add an idle thread to idle list Void CthreadPool :: appendtoidlelist (corkerthread * jobthread) { m_idlemutex.lock (); m_idlelist.push_back (jobthread); m_threadlist.push_back (jobthread); m_idlemutex.unlock (); } //move and idle thread to busy thread Void CthreadPool :: MoveTobusylist (CWORKERTHREAD * IDLETHREAD) { m_busymutex.lock (); M_busylist.push_back (idlethread); m_availnum--; m_busymutex.unlock (); m_idlemutex.lock (); Vector POS = find (m_idlelist.begin (), m_idlelist.end (), idlethread); IF (POS! = m_idlelist.end ()) m_idlelist.ed (POS); m_idlemutex.unlock (); } Void CthreadPool :: MoveToidList (CWORKERTHREAD * BUSYTHREAD) { m_idlemutex.lock (); m_idlelist.push_back (busythread); m_availnum ; m_idlemutex.unlock (); m_busymutex.lock (); Vector POS = Find (m_busylist.begin (), m_busylist.end (), busythread; IF (POS! = m_busylist.end ()) m_busylist.ed; m_busymutex.unlock (); m_idlecond.signal (); m_maxnumcond.signal (); } // Create Num iDle thread and put the to idlelist Void CthreadPool :: CreateIDLethread (int Num) { For (int i = 0; I Thr-> setthreadpool (this); AppendToidList (THR); m_varmutex.lock (); m_availnum ; m_varmutex.unlock (); Thr-> start (); // begin the thread, The Thread Wait For Job } } Void CthreadPool :: DeleteidLethread (int Num) { Printf ("Enter Into CthreadPool :: DeleteidleThread / N"); m_idlemutex.lock (); Printf ("Delete Num IS% D / N", NUM); For (int i = 0; i CWORKERTHREAD * THR; IF (m_idlelist.size ()> 0) { THR = (CWORKERTHREAD *) m_idlelist.front (); Printf ("Get Idle Thread% D / N", thr-> getthreadId ()); } Vector POS = find (m_idlelist.begin (), m_idlelist.end (), tH); IF (POS! = m_idlelist.end ()) m_idlelist.ed (POS); m_availnum--; Printf ("THE Idle Thread Available Num:% D / N", M_Availnum); Printf ("THE IDLELIST NUM:% D / N", M_IDLELIST.SIZE ()); } m_idlemutex.unlock (); } Void CthreadPool :: Run (CJOB * Job, Void * JobData) { Assert (Job! = null); // if The busy thread number adds to m_maxnum, so we stay wait IF (getBusynum () == m_maxnum) m_maxnumcond.wait (); IF (m_idlelist.size () { IF (getNum () m_initnum-m_idlelist.size () CreateIDLethread (m_initnum-m_idlelist.size ()); Else CreateIDLethread (m_maxnum-getAllnum ()); } CWORKERTHREAD * IDLETHR = GetIdLethread (); IF (IDLETHR! = NULL) { IDLETHR-> M_WORKMUTEX.LOCK (); MoveTobusylist (IDLethR); Idlethr-> setthreadpool (this); Job-> setworkthread (iDLethR); Printf ("Job IS Set to Thread% D / N", IDLethR-> getthreadId ()); IDLETHR-> SetJob (Job, JobData); } } There are two linked lists in CThreadPool, one is an idle chain table, one is a busy list. All idle processes are stored in the IDle linked list, when the thread performs task, its status becomes busy, and removes from the idle chain table and moves to the busy chain table. In the constructor of the CTHREADPOOL, we will perform the following code: for (int i = 0; i { CWORKERTHREAD * THR = New CWORKERTHREAD (); AppendToidList (THR); Thr-> setthreadpool (this); Thr-> start (); // begin the thread, The Thread Wait For Job } In this code, we will create M_initnum threads. After creating, call AppendToidLIST in the IDLE list, because there is currently no task to send these threads, so threads will hang themselves after performing START. In fact, the number of threads accommodated in the thread pool is not a constant, which will automatically retract according to the execution load. To this end, set four variables in CTHREADPOOL: m_initnum: The number of threads in the thread pool when you are interchanged. M_maxNum: The maximum number of threads allowed concurrently in the current thread pool. M_availlow: The minimum number of idle threads allowed in the current thread pool, if the number of idle is lower than this value, indicating that the load may be too heavy, and it is necessary to increase the number of idle thread pools. In implementation, we always adjust the thread to m_initnum. M_availHigh: The maximum number of idle threads allowed in the current thread pool, if the number of idle is higher than this value, indicating that the current load can be lighter, and the extra idle thread will be deleted, and the adjustment number is also m_initnum. m_availnum: The number of threads actually exists in the thread pool, and its value is between M_availHigh and M_availlow. If the number of threads is always maintained between M_Availlow and M_AvailHigh, the thread is neither created, nor does it need to be deleted, maintain a balanced state. Therefore, how to set the value of M_Availlow and M_availHigh so that the maximum possible maintenance balance state of the thread pool is the problem that the thread pool design must be considered. Thread pools After accepting new tasks, the thread pool first checks if there is enough free pool available. The check is divided into three steps: (1) Check if the thread currently in a busy state reaches the set maximum M_maxNum. If it is reached, it indicates that there is no idle thread available, and you can't create new threads, so you must wait until you have a thread to return to free. In the queue. (2) If the current number of idle threads is less than the minimum number of idle numbers we set, we must create new threads. By default, the number of threads after the creation should be m_initnum, so the number of threads created should be (current The number of idle threads and m_initnum); however, there is a special case must be considered, that is, the existing thread is plus the number of threads after the creation may exceed M_MaxNum, so we must take the creation of threads. IF (getNum () m_initnum-m_idlelist.size () CreateIDLethread (m_initnum-m_idlelist.size ()); Else CreateIDLethread (m_maxnum-getAllnum ()); If the total number of created does not exceed M_maxNum, the created thread is m_initnum; if it is more than, only (M_MaxNum-current thread total) is created. (3) Call the GetIdLethread method to find the idle thread. If there is currently no idle thread, hang; otherwise assign the task to the thread while moving it into the busy queue. When the thread is executed, it will call the MoveToidList method into the idle chain table, which also calls the m_idlecond.signal () method to wake up the thread that may block in GetIDLethread (). CWORKERTHREAD CWORKERTHREAD is a derived class of CThread, which is a fact working thread. In the CTHREADPOOL constructor, we created a certain number of CWORKERTHREAD. Once these threads are created, we will call START () to start the thread. The Start method will eventually call the RUN method. The RUN method is an infinite loop process. When there is no actual task, M_JOB is NULL, at which time the thread will call the WAIT method to wait, thereby being suspended. Once the thread pool distributes the specific task to the thread, it will be awakened, thereby notifying the thread to continue executing from the suspended place. The integr definition of CWORKERTHREAD is as follows: Class CWORKERTHREAD: PUBLIC CTHREAD { Private: Cthreadpool * m_threadpool; CJOB * m_job; Void * m_jobdata; CThreadMutex M_Varmutex; BOOL M_ISEND; protected: PUBLIC: CCondition M_JobCond; CthreadMutex M_Workmutex; CWORKERTHREAD (); Virtual ~ corkerthread (); Void Run (); Void SetJob (CJOB * Job, Void * JobData); CJOB * getJob (void) {return m_Job;} Void SetThreadPool (CTHREADPOOL * THRPOOL); Cthreadpool * getthreadpool (void) {Return M_ThreadPool;} } CWORKERTHREAD :: CWORKERTHREAD () { m_Job = NULL; m_jobdata = null; m_threadpool = NULL; m_isnd = false; } CWORKERTHREAD :: ~ CWORKERTHREAD () { IF (NULL! = m_JOB) Delete M_Job; IF (M_ThreadPool! = NULL) DELETE M_THREADPOOL; } Void CWORKERTHREAD :: Run () { SetthreadState (Thread_Running); For (;;) { While (m_job == null) m_jobcond.wait (); M_JOB-> Run (M_JobData); m_job-> setworkthread (null); m_Job = NULL; m_threadpool-> movetoidlelist (this); IF (m_threadpool-> m_idlelist.size ()> m_threadpool-> getAvailHighnum ()) { m_threadpool-> deleteidLethread (m_threadpool-> m_idlelist.size () - m_threadpool-> getinitnum ()); } m_workmutex.unlock (); } } Void CWORKERTHREAD :: SetJob (CJOB * Job, Void * JobData) { m_varmutex.lock (); m_job = job; m_jobdata = jobdata; Job-> setworkthread (this); m_varmutex.unlock (); m_jobcond.signal (); } Void CWORKERTHREAD :: SetthreadPool (CTHREADPOOL * THRPOOL) { m_varmutex.lock (); m_threadpool = thrpool; m_varmutex.unlock (); } When the thread performs tasks, you must first determine if the number of idle threads is lower than m_availlow, if it is below, you must create enough free threads to reach m_initnum, then call MoveTobusylist () to remove the idle queue, move into the busy queue. When the task is executed, it calls MoveToidList () to move the busy queue, move into the idle queue, waiting for a new task. In addition to the RUN method, another important method in cforkerthread is setJob, which assigns actual tasks to threads. When no task is M_JOB is NULL, the thread will call M_JobCond.Wait to wait. Once Job is assigned to the thread, it will call the m_jobcond.signal method to wake up the thread. Since M_JobCond is a variable within the thread, each thread maintains a m_jobcond, only the thread gets the thread is awakened, and the task will continue to wait. Whenever a thread is awake, it will continue M_Job-> Run (M_JobData) from the waiting place, which is where the thread performs the actual task. During the thread performs a given job, we must prevent another Job from assigning the thread, so before assigning, the Job is executed by m_varmutex, and the Job execution will not be associated with the thread; the task is executed, we Call m_varmutex.unlock () to unlock, at this time, threads can also accept new execution tasks. Before the thread execution task returns an idle queue, we also need to judge whether the thread in the current idle queue is higher than M_AVailHigh. If you exceed M_AvailHigh, you must delete (m_threadpool-> m_idlelist.size () - m_threadpool-> getinitnum ()) thread, keep the number of threads in m_initnum. CJOB The CJOB class is relatively simple, which encapsulates the basic properties and methods of the task, where the most important thing is the RUN method, the code is as follows: Class CJOB { Private: Int m_jobno; // the num WAS Assigned to the job Char * m_jobname; // the Job Name Cthread * m_pworkthread; // the thread associated with the job PUBLIC: CJOB (void); Virtual ~ CJOB (); INT getJobno (void) const {return m_jobno;} void setjobno {m_jobno = jobno; Char * getjobname (void) const {return m_jobname;} Void setjobname (char * jobname); Cthread * getWorkthread (void) {return m_pworkthread;} Void setWorkthread (CTHREAD * PWORKTHREAD) { m_pworkthread = pworkthread; } Virtual Void Run (Void * PTR) = 0; } CJOB :: CJOB (Void) : m_pworkthread (null) , m_jobno (0) , M_JobName (NULL) { } CJOB :: ~ CJOB () { IF (NULL! = m_jobname) Free (m_jobname); } Void CJOB :: SetJobName (Char * JobName) { IF (null! = m_jobname) { Free (m_jobname); m_JobName = NULL; } IF (NULL! = JobName) { m_jobname = (char *) Malloc (Strlen (JobName) 1); STRCPY (M_JobName, JobName); } } Thread pool usage example So we gave a simple thread pool frame that is not related to specific tasks. Using this frame is very simple, what we need is to derive the CJOB class, which will need to be completed in the RUN method. The Job is then delivered to the CTHReadManage. Below we give a simple sample program Class CxJob: Public CJOB { PUBLIC: CXJOB () {i = 0; ~ Cxjob () {} Void Run (void * jobdata) { Printf ("THE Job Comes from CxJOB / N); Sleep (2); } } Class cyjob: public cjob: Public CJOB { PUBLIC: Cyjob () {i = 0; ~ Cyjob () {} Void Run (void * jobdata) { Printf ("THE Job Comes from Cyjob / N); } } Main () { CthreadManage * Manage = New CthreadManage (10); For (int i = 0; i <40; i ) { CXJOB * JOB = New CXJOB (); Manage-> Run (Job, Null); } Sleep (2); Cyjob * job = new cyjob (); Manage-> Run (Job, Null); Manage-> terminateAll (); } CXJOB and CYJOB are inherited from the Job class, which implements the RUN interface. CXJOB is just a simple print "The Job Comes from CxJob", and Cyjob also prints "The Job Comes from Cyjob" and then sleeps for 2 seconds. In the main program we initially create 10 working threads. Then, 40 CXJOBs and one cyjob are then performed separately. Thread pool after use Thread pool suitable for occasions In fact, the thread pool is not universal. It has its specific use occasions. The thread pool is committed to reducing the impact of the overhead of thread itself on the application. This is premised on the thread itself is not negligible compared to thread execution tasks. If the overhead of the thread itself is negligible relative to the thread task, the benefits of the thread pool are not obvious, such as for the FTP server and the Telnet server, usually transmitted for a long time, The overhead is large, then, when we use a thread pool that is not necessarily an ideal method, we can choose the "Instant Creating, Instant Destruction" policy. In short, the thread pool is usually suitable for the following occasions: (1) Frequently handled tasks within unit time, short task processing time (2) High requirements for real-time. If you are creating a thread after accepting the task, you can't meet the real-time requirements, so you must use a thread pool to prepreg. (3) It is necessary to face high sudden events, such as a web server, if there is a soccer broadcast, the server will produce a huge impact. At this point, if you take the traditional method, you must have a large number of threads, destroy the thread. At this point, the dynamic thread pool can be used to avoid this happening. Conclude This article gives a simple unrelated thread-independent thread pool implementation, through which the thread pool can greatly simplify the development of multi-threads under Linux. The further improvement of the threading pool is still in progress, hoping to get your advice and support. Reference http://www-900.ibm.com/developerWorks/cn/java/J-JTP0730/index.shtml, Java Theory and Practice: Thread Pool and Work Queue POSIX multi-threaded programming, David R.Butenhof translator: Yu Lei Zeng Gang, China Electric Press C object-oriented multi-thread programming, cameron hughes is waiting Zhou Liangzhong, People's Posts and Telecommunications Java Pro, combined with threads and analyzer pools, EDY YU About author Zhang Zhongqing, Xi'an Jiaotong University Software, Reading Master, current research direction is a distributed network and mobile middleware, which is extremely hobby for Linux, can contact me through flydish1234@sina.com.cn.