This is a simple application of the pthread thread
1. Implements the concept of thread pool, which can be reused by threads.
2. The signal volume, mutual exclusion lock, etc. encapsulation, business processing function only need to write and business-related code.
3. Good portability. If you want to apply this thread pool code to your implementation, just write your own business processing functions and rewrite the work-queue data processing methods.
Sample code mainly includes a main program and two thread implementation classes
ThreadTest.cpp: Main program
Cthreadmanager: Thread management class, implementation classes of thread pools
Cthread: Thread class.
The main program implementation method.
1. Implement the main function and a business function that requires threading (the business function in the example code is a simple computational function count). Create an instance of Cthreadmanager in the main function to generate a thread pool. This time, the business function as a function pointer to the Cthreadmanager inside, will eventually be called by the thread.
2. Put the data in the work queue to be processed by the business function.
3. Set the semaphore, wake the thread.
function
int Count (int nwork)
{
int nresult = nwork * nwork
to be executed by the thread; printf ("Count result is%d\n", nresult);
return 0;
}
int main () {
//creates an instance of the thread management class that passes the thread function and maximum number of threads to be executed
cthreadmanager* Pmanager = new Cthreadmanager (Count, 3);
Put the calculated number into the work Queue
Pmanager->pushworkque (5);
Pmanager->pushworkque (a);
Set the semaphore, wake the thread
Pmanager->postsem ();
Pmanager->postsem ();
Wait for child thread to perform sleep
(1);
return 0;
}
The method of Cthreadmanager implementation
1. Encapsulate the semaphore and mutex into its own function,
2. In the new method, loops call the Cthread new method, starting a certain number (configurable) thread, generating the thread pool.
3. When these threads are started, the Managefuction function in Cthreadmanager is executed. This function is infinitely cyclic, ensuring that the thread is not destroyed throughout the lifetime of the program.
4. In the loop, the first line of code is waiting for a semaphore, which is set by the main program, where all threads are blocked if they are not set (representing a job that does not need to be handled for the time being).
4. Once the semaphore is set, according to the Linux thread scheduling mechanism, one of the threads in the blocked thread queue is awakened and can execute the following code.
5. the data to be processed from the work queue (exclusive with a mutex)
6. The function pointer invokes the business function passed by the main function to process the data.
After the 7. business function finishes, the thread enters the next loop, waiting for the new semaphore.
Class Cthreadmanager {friend void* managefuction (void*); private:sem_t M_sem; Signal volume pthread_mutex_t M_mutex; Mutual-exclusion lock queue<int> m_quework; Work Queue list<cthread*> M_lstthread; Thread list int (*m_threadfuction) (int);
function pointer, which points to the thread execution function public:cthreadmanager (int (*threadfuction) (int), int nmaxthreadcnt) passed through the main function;
Virtual ~cthreadmanager ();
int Waitsem ();
int Postsem ();
int Lockmutex ();
int Unlockmutex ();
void Pushworkque (int nwork);
int Popworkque ();
int runthreadfunction (int nwork);
}; The thread executes the function, it's just a shell, handles semaphores and mutexes, and//finally calls the thread execution function passed by the main function to implement business processing void* managefuction (void* argv) {cthreadmanager* Pmanager =
(cthreadmanager*) argv;
An infinite loop (meaning that the thread is not destroyed, reused) while (true) {//The thread is open, blocking here until the main function sets the semaphore Pmanager->waitsem ();
printf ("Thread wakeup.\n");
Remove the number of Pmanager->lockmutex () to be processed from the work queue;
int nwork = Pmanager->popworkque ();
Pmanager->unlockmutex ();
printf ("Call Count function.\n"); pmanager-&Gt
Runthreadfunction (nwork);
return 0;
}//Construction method Cthreadmanager::cthreadmanager (int (*threadfuction) (int), int nmaxthreadcnt) {sem_init (&m_sem, 0, 0);
Pthread_mutex_init (&m_mutex, NULL);
M_threadfuction = threadfuction;
for (int i=0; i<nmaxthreadcnt; i++) {cthread* pThread = new Cthread (managefuction, this);
printf ("Thread started.\n");
M_lstthread.push_back (PThread);
}
}
The method of Cthread implementation
Cthreadmanager is simpler, encapsulating functions that create threads and join threads.
Cthread::cthread (void* (*threadfuction) (void*), void* threadargv)
{
//Initialize thread properties
pthread_attr_t threadattr;
Pthread_attr_init (&threadattr);
Pthread_create (&m_thread, &threadattr, Threadfuction, threadargv);
C + + thread pool, inherit cdoit, implementation of which start and end
/* Multithreading Management * */#ifndef cthreadpoolmanage_h #define CTHREADPOOLMANAGE_H #include <iostream> #include <pth read.h> #include <unistd.h> #include <list> #include <vector> #include <time.h> #include <
asm/errno.h> #define USLEEP_TIME #define CHECK_TIME 1 using namespace std;
Class Cdoit {public:virtual int start (void *) {};
virtual int end () {};
}; Class Cthreadpoolmanage {Private:int _minthreads; Keep at least several threads int _maxthreads; Can have a maximum of several threads int _waitsec;
How many seconds to idle will turn the thread off class threadinfo{Public:threadinfo () {isbusy = false;
Doflag = true;
}//pthread_mutex_t Mtx=pthread_mutex_initializer;
pthread_cond_t Cond=pthread_cond_initializer; BOOL IsBusy;
whether free bool Doflag; time_t BeginTime; Thread does not work start time pthread_t cthreadpid; Thread ID pthread_attr_t cthreadattr; Thread Properties Cdoit * doit; Task class void * value;
The value to be passed};
thread function static void* startthread (void*); Task Queue Lock PThread_mutex_t _duty_mutex;
Task Queue list<threadinfo*> _dutylist;
Thread queue lock pthread_mutex_t _thread_mutex;
Thread Queue list<threadinfo*> _threadlist;
Initialize, create a minimum number of threads///void Initthread ();
Task assignment thread///static void* taskallocation (VOID*ARG);
pthread_t Tasktpid;
Thread destroy, stateful check thread///static void* checkthread (void* Arg);
pthread_t Checktpid;
BOOL Checkrun;
Thread exception exits clean static void Threadcleanup (void* arg);
int Addthread (list<threadinfo*> *plist,threadinfo* ptinfo);
Public:cthreadpoolmanage ();
* * Reserved minimum thread, maximum number of threads, idle how long to destroy, keep several threads redundant/cthreadpoolmanage (int min,int max,int waitsec);
~cthreadpoolmanage ();
int start ();
Task Injector int Putduty (cdoit *,void *);
int Getnowthreadnum ();
};
#endif//Cthreadpoolmanage_h
CPP
* * thread pool, Threading management class */#include "cthreadpoolmanage.h" Cthreadpoolmanage::cthreadpoolmanage () {_minthreads = 5; Minimum number of threads _maxthreads = 5; Can have a maximum of several threads _waitsec = 10;
Idle number of seconds after the thread is closed Pthread_mutex_init (&_duty_mutex, NULL);
Pthread_mutex_init (&_thread_mutex, NULL);
Checkrun = true;
Cthreadpoolmanage::cthreadpoolmanage (int min, int max, int waitsec) {cthreadpoolmanage (); _minthreads = min; Keep at least a few threads _maxthreads = max; Can have a maximum of several threads _waitsec = waitsec; How many seconds to idle turn the thread off} cthreadpoolmanage::~cthreadpoolmanage () {} void Cthreadpoolmanage::threadcleanup (void* arg) {thread
info* tinfo = (threadinfo*) arg;
Tinfo->isbusy = false;
Pthread_mutex_unlock (&TINFO->MTX);
Pthread_attr_destroy (&TINFO->CTHREADATTR);
Delete Tinfo;
} void* Cthreadpoolmanage::startthread (void* Arg) {cout<< "thread started work" <<endl;
threadinfo* tinfo = (threadinfo*) arg;
Pthread_cleanup_push (THREADCLEANUP,ARG); while (Tinfo->doflag) {Pthread_mutEx_lock (&TINFO->MTX);
if (Tinfo->doit = = NULL) {cout<< "Start waiting for task" <<endl;
Pthread_cond_wait (&TINFO->COND,&TINFO->MTX);
cout<< "Got a job." <<endl;
} Tinfo->isbusy = true;
Tinfo->doit->start (Tinfo->value);
Tinfo->doit->end ();
tinfo->doit=null;
Tinfo->isbusy = false;
Time (&tinfo->begintime);
Pthread_mutex_unlock (&TINFO->MTX);
//0 Normal execution Here does not perform cleanup functions, the exception executes Pthread_cleanup_pop (0);
Pthread_attr_destroy (&TINFO->CTHREADATTR);
Delete Tinfo;
cout<< "Thread End" <<endl;
} void Cthreadpoolmanage::initthread () {int i = 0;
for (i = 0;i<this->_minthreads;i++) {threadinfo *tinfo = new Threadinfo;
Tinfo->doit = NULL;
Tinfo->value = NULL;
Tinfo->isbusy = false;
Tinfo->doflag = true;
Pthread_create_detached (Detach thread) and PTHREAD _create_joinable (non-detached threads) pthread_attr_init (&tinfo->cthreadattr); Pthread_attr_setdetachstate (&tinfo->cthreadattr,pthread_create_detached);
cout<< "Initialization of a thread" <<endl; if (Pthread_create (&tinfo->cthreadpid,&tinfo->cthreadattr,startthread, (void *) Tinfo)!= 0) {cout<& lt; "
Create thread Failed "<<endl;
Break
} this->_threadlist.push_back (Tinfo); } int Cthreadpoolmanage::addthread (std::list< cthreadpoolmanage::threadinfo* >* plist, CthreadPoolManage::
threadinfo* ptinfo) {threadinfo *tinfo = new Threadinfo;
Tinfo->doit = ptinfo->doit;
Tinfo->value = ptinfo->value;
Tinfo->isbusy = true; if (Pthread_create (&tinfo->cthreadpid,null,startthread, (void *) Tinfo)!= 0) {cout<< ' Create thread failed ' <<
Endl
return-1;
} plist->push_back (Tinfo);
return 0;
int cthreadpoolmanage::p utduty (cdoit* doit, void* value) {threadinfo *tinfo = new Threadinfo;
Time (&tinfo->begintime);
Tinfo->doit= doit;
Tinfo->value = value;
Pthread_mutex_lock (&_duty_mutex); This->_dutylist.push_back (tinfo);
Pthread_mutex_unlock (&_duty_mutex);
return 0;
} void* cthreadpoolmanage::taskallocation (void*arg) {cthreadpoolmanage * ptmanage = (cthreadpoolmanage*) arg;
int size_1 = 0;
int size_2 = 0;
int i_1 = 0;
int i_2 = 0;
bool A_1 = true;
bool a_2 = true;
threadinfo* Ptinfo;
threadinfo* ptinfotmp;
while (true) {size_1 = 0;
size_2 = 0;
Pthread_mutex_lock (&ptmanage->_duty_mutex);
Pthread_mutex_lock (&ptmanage->_thread_mutex);
Size_1 = Ptmanage->_dutylist.size ();
Size_2 =ptmanage->_threadlist.size (); for (List<threadinfo*>::iterator itorti1 = Ptmanage->_dutylist.begin (); Itorti1!=ptmanage->_
Dutylist.end ();)
{ptinfo = *itorti1;
A_1 = true; for (List<threadinfo*>::iterator Itorti2 = Ptmanage->_threadlist.begin (); itorti2!=ptmanage->_
Threadlist.end (); itorti2++) {ptinfotmp = *itorti2;
if (Ebusy = = Pthread_mutex_trylock (&PTINFOTMP->MTX)) {continue;
} if (!ptinfotmp->isbusy) { Ptinfotmp->doit = ptinfo->doit;
Ptinfotmp->value = ptinfo->value;
Ptinfotmp->isbusy = true;
Pthread_cond_signal (&ptinfotmp->cond);
Pthread_mutex_unlock (&PTINFOTMP->MTX);
A_1 = false;
Delete Ptinfo;
Break
} pthread_mutex_unlock (&PTINFOTMP->MTX); } if (a_1) {if (Ptmanage->_threadlist.size () >ptmanage->_maxthreads| |
Ptmanage->addthread (&ptmanage->_threadlist,ptinfo)!=0) {itorti1++;
Continue
}else{itorti1 = ptmanage->_dutylist.erase (ITORTI1);
} Delete ptinfo;
}else{itorti1 = ptmanage->_dutylist.erase (ITORTI1);
} pthread_mutex_unlock (&ptmanage->_duty_mutex);
Pthread_mutex_unlock (&ptmanage->_thread_mutex);
Usleep (Usleep_time);
return 0;
} void* Cthreadpoolmanage::checkthread (void* arg) {cthreadpoolmanage * ptmanage = (cthreadpoolmanage*) arg;
threadinfo* Ptinfo;
time_t Nowtime; while (Ptmanage->checkrun) {SLEEP (Check_time);
Pthread_mutex_lock (&ptmanage->_thread_mutex); if (Ptmanage->_threadlist.size () <=ptmanage->_minthreads) {Pthread_mutex_unlock (&ptmanage->_
Thread_mutex);
Continue for (List<threadinfo*>::iterator Itorti2 = Ptmanage->_threadlist.begin (); itorti2!=ptmanage->_
Threadlist.end ();) {ptinfo = *itorti2;
if (Ebusy = = Pthread_mutex_trylock (&ptinfo->mtx)) {itorti2++;
Continue
} time (&nowtime); if (Ptinfo->isbusy = = False && nowtime-ptinfo->begintime>ptmanage->_waitsec) {Ptinfo->doflag =
False
Itorti2 = Ptmanage->_threadlist.erase (ITORTI2);
}else{itorti2++;
} pthread_mutex_unlock (&PTINFO->MTX);
} pthread_mutex_unlock (&ptmanage->_thread_mutex);
} int Cthreadpoolmanage::start () {//initializing this->initthread (); Start Task Assignment Thread if (Pthread_create (&tasktpid,null,taskallocation, (void *) this)!= 0) {cout<< "Create task assignment thread failed" << ; Endl;
return-1; }//Create a current state assignment management thread if (Pthread_create (&checktpid,null,checkthread, (void *) this)!= 0) {cout<< Create thread state assignment management thread
Failure "<<endl;
return-1;
return 0;
}///////////////////////////////int Cthreadpoolmanage::getnowthreadnum () {int num = 0;
Pthread_mutex_lock (&this->_thread_mutex);
num = This->_threadlist.size ();
Pthread_mutex_unlock (&this->_thread_mutex);
return num;
}