Introduction to Thread pool programming:
in our service-side program, we use a lot of concepts about pools, thread pools, pool of connections, memory pools, object pools, and so on. Using the concept of pool can efficiently utilize server-side resources, such as the lack of a large number of threads in the system to switch context, a database connection pool, but also need to maintain a certain connection, rather than occupy a lot of database connection resources. They also avoid time-consuming operations, such as creating a thread, requesting a database connection, and probably just using it once, and then immediately releasing the resource you just requested, which is inefficient.
In my last blog has implemented a line base class, here we only need to implement a thread pool class ThreadPool and the thread pool scheduling worker class Workthread can be, and Workthread is inherited from the Thread class.
Implementation ideas:
a simple thread pool implementation is generally as follows:
- Create multiple threads (WORKTHREADK objects) in ThreadPool , each of which is in a blocked state, waiting for the task to arrive
- ThreadPool provides an interface for submitting tasks, such as Post_job (proccallback func, void* data), and returns immediately after Post_job without blocking
- ThreadPool maintains an idle thread queue, and when the client program calls Post_job () , if there are idle threads in the idle queue, remove a thread handle and set the task to give a new task notification event. The processing waiting thread snaps to the event signal and starts executing the task, pushing the thread handle back to the idle thread queue after execution
- The thread pool takes a callback function
First we implement a Workthread class:
#include <pthread.h>#include<vector>#include<iostream>using namespaceStd;typedefvoid(*proccallback) (void*);classWorkthread;classthreadpool{friendclassWorkthread; Public: ThreadPool () {}~ThreadPool (); intStart_thread_pool (size_t thread_num =5);//start a thread_num thread intStop_thread_pool ();//Wire Harness Thread pool voidDestroy ();//destroy the resources requested by the thread pool voidPost_job (Proccallback func,void* data);//submit the task interface, passing in the callback function address and parametersprotected: Workthread* Get_idle_thread ();//Gets a thread handle from the Get idle queue voidAppend_idle_thread (workthread* pthread);//add to Thread_vec_ and Idl_que_ voidMove_to_idle_que (workthread* idlethread);//adding a thread handle to the Idle_que_Private: size_t thr_num_; //Number of ThreadsVector<workthread*> thr_vec_;//Thread Handle CollectionVector<workthread*> Idle_que_;//Idle thread QueuePrivate: //Not implementThreadPool (Constthreadpool&); ThreadPool&operator=(Constthreadpool&);};classworkthread{friendclassThreadPool; Public: Workthread (ThreadPool*Pthr_pool) {Hr_pool_=Pthr_pool; CB_FUNC_=NULL; PARAM_=NULL; } ~Workthread () {}voidSet_job (Proccallback func,void*param) {cb_func_=func; PARAM_=param; //notify (); } voidrun () {if(cb_func_) {cb_func_ (PARAM_); } cb_func_=NULL; PARAM_=NULL; Hr_pool_->move_to_idle_que ( This); }Private: ThreadPool*Hr_pool_; Proccallback cb_func_; void*param_;};
The key to thread pool implementation is how to create multiple threads, and when a task is temporarily able to take a thread from the thread pool (that is, to get a pointer to one of the threads), then submit the task and execute it. Another point is that when the task is finished, the thread handle should be re-added to the idle thread queue, so we passed the ThreadPool pointer to Workthread,thr_pool_ and finally can call Move_to_idle_que (this) To move the thread handle to the free queue.
Some of the key code implementations in ThreadPool:
#include"threadpool.h"#include<cstdio>classThreadPool;intThreadpool::start_thread_pool (size_t thread_num) {thr_num_=Thread_num; intRET =0; for(size_t i =0; i < thr_num_; ++i) {workthread* Pthr =NewWorkthread ( This); //pthr->set_thread_id (i); if(ret = Pthr->hr_pool_->start_thread_pool ())! =0) {printf ("start_thread_pool:failed When create a work thread:%d\n", i); DeletePthr; returni; } append_idle_thread (PTHR); } returnthr_num_;}intThreadpool::stop_thread_pool () { for(size_t i =0; I < thr_vec_.size (); ++i) {workthread* Pthr =Thr_vec_[i]; //Pthr->join (); DeletePthr; } thr_vec_.clear (); Idle_que_.clear (); return 0;}voidThreadPool::d Estroy () {Stop_thread_pool ();}voidThreadpool::append_idle_thread (workthread*pthread) {Thr_vec_.push_back (pthread); Idle_que_.push_back (pthread);}voidThreadpool::move_to_idle_que (workthread*idlethread) {Idle_que_.push_back (idlethread);} Workthread*Threadpool::get_idle_thread () {Workthread* Pthr =NULL; if(!Idle_que_.empty ()) {Vector<workthread*>::iterator it =Idle_que_.end (); Pthr= *it; Idle_que_.pop_back (); } returnPthr;}voidThreadPool::p ost_job (Proccallback func,void*data) {Workthread* Pthr =Get_idle_thread (); while(Pthr = =NULL) { //Sleep (500000);Pthr =Get_idle_thread (); } pthr-Set_job (func, data);}voidCountvoid*param) { //Do Some your work, like: int* pi = static_cast<int*>(param); intval = *pi +1; printf ("val=%d\n", Val); DeletePi;}intMain () {//The program is used as follows:threadpool* PTP =NewThreadPool (); PTP->start_thread_pool (3);//Start 3 ThreadsPtp->post_job (Count,New int(1));//Submit a TaskPtp->post_job (Count,New int(2)); PTP->post_job (Count,New int(3)); //when the program wiring harnessPtp->Stop_thread_pool (); return 0;}
Implementation of the C + + thread pool