LINUX C++ 线程池简单实现之双队列

来源:互联网 发布:她在睡梦中 知乎 编辑:程序博客网 时间:2024/05/21 07:12

1 线程池原理

线程池的原理很简单,就是预先建立些空闲线程,并把它们投入睡眠中。当有任务到达时,就唤醒一个线程来处理,处理完后放回线程池中。因为线程池对空闲线程的维护,所以避免了对线程创建的开销,当频繁使用线程且处理工作量很小的情况下,使用线程池可以有效的提升系统性能。

2 线程池实现

线程池的实现主要分为四部分,线程的创建、添加任务到线程池中、子线程取出任务进行处理以及把执行完成的任务写回主线程。
使用线程池的一般是为了防止主线程阻塞,所以把阻塞的任务(如读写磁盘等)交予子线程处理,实现方式一般分为双队列(同时使用互斥锁和条件变量)和管道两种。
使用双队列的是因为在主线程非阻塞模式下,获取互斥锁时只能用try_lock的方式,从而不一定能获取到互斥锁,所以放任务时需要使用两个队列,当获取不到锁时就放入另一个队列,一个队列的任务执行完后,交换两队列;

3 双队列线程池程序实现:

头文件: 18 #ifndef __CTHREAD 19 #define __CTHREAD 20  21 #include<queue> 22 #include<string> 23 #include<pthread.h> 24 #include<iostream> 25 using namespace std; 26  27 28 class CTask 29 { 30     protected: 31         string m_strTaskName; 32         void *m_ptrData; 33     public: 34     35 36         CTask(){} 37  38         CTask(string taskName) 39         { 40             this->m_strTaskName=taskName; 41             m_ptrData=NULL; 42         } 43         virtual int Run()=0; 44         void SetData(void *data);  //设置任务数据 45  46 }; 47  48 49 class CThreadPool 50 { 51     private: 52          int m_threadNum;                       //线程数量   53  54          static pthread_mutex_t  m_threadMutex; 55          static pthread_mutex_t  m_taskMutex; 56          static pthread_cond_t   m_threadCond; 57          static pthread_cond_t   m_taskCond; 58  59          static queue<CTask*>* taskQueue1;        //任务队列1 60          static queue<CTask*>* taskQueue2;        //任务队列2 61          static queue<CTask*>* taskback;          //任务返回队列  62    public: 63          CThreadPool(int); 64          static int swapqueue(queue<CTask *>* &,queue<CTask*>* &);   //交换任务队列1和任务队列2的任务 65          static void* ThreadFunc(void *arg); 66          int Create(); 67          int AddTask(CTask*);           //加入任务 68          CTask* GetTaskback();                   //返回任务 69          int Check(); 70          static int clearQueue(queue<CTask*>*); 71          ~CThreadPool(); 72  73 }; 74  75 #endifcpp文件:     18 #include"CThread.h" 19 #include<string> 20 #include<iostream> 21 using namespace std; 22  23 void CTask::SetData(void *data) 24 { 25     m_ptrData=data; 26 } 27  28 queue<CTask*>* CThreadPool::taskQueue2=new queue<CTask*>[1]; 29 queue<CTask*>* CThreadPool::taskQueue1=new queue<CTask*>[1]; 30 queue<CTask*>* CThreadPool::taskback=new queue<CTask*>[1]; 31  32 pthread_mutex_t CThreadPool::m_threadMutex=PTHREAD_MUTEX_INITIALIZER; 33 pthread_mutex_t CThreadPool::m_taskMutex=PTHREAD_MUTEX_INITIALIZER; 34 pthread_cond_t CThreadPool::m_threadCond=PTHREAD_COND_INITIALIZER; 35 pthread_cond_t CThreadPool::m_taskCond=PTHREAD_COND_INITIALIZER; 36  37 CThreadPool::CThreadPool(int threadNum) 38 { 39     this->m_threadNum=threadNum; 40     Create(); 41 } 42  43 int CThreadPool::swapqueue(queue<CTask*>* &a,queue<CTask*>* &b)  //交换两个队列 44 {    45      queue<CTask*>* temp; 46      temp=a; 47      a=b; 48      b=temp;   cout<<"swap!!!!!"<<endl; 49 } 50  51 void *CThreadPool::ThreadFunc(void *arg)    52 { 53     pthread_t tid=pthread_self(); 54     while(1) 55     { 56         CTask *task; 57         if(taskQueue1->empty()&&!taskQueue2->empty()) 58             swapqueue(taskQueue1,taskQueue2); 59  60         pthread_mutex_lock(&m_threadMutex); 61  62         if(taskQueue1->empty()) 63         { 64            pthread_cond_wait(&m_threadCond,&m_threadMutex); 65            pthread_mutex_unlock(&m_threadMutex); 66            continue; 67         } 68  69         task=taskQueue1->front(); 70         taskQueue1->pop(); 71         pthread_mutex_unlock(&m_threadMutex); 72  73         task->Run(); 74  75         pthread_mutex_lock(&m_taskMutex); 76         taskback->push(task); 77         //pthread_cond_signal(&m_taskCond); 78         pthread_mutex_unlock(&m_taskMutex); 79  80     } 81     return 0; 82 } 83  84 int CThreadPool::AddTask(CTask *task)    //添加任务到线程池中 85 { 86     if(pthread_mutex_trylock(&m_threadMutex)==0) 87     { 88         taskQueue1->push(task); 89         pthread_cond_signal(&m_threadCond); 90         cout<<"add to queue1"<<endl; 91         pthread_mutex_unlock(&m_threadMutex); 92  93     }else 94     { 95         taskQueue2->push(task); 96         pthread_cond_signal(&m_threadCond); 97         cout<<"add to queue2"<<endl; 98         pthread_mutex_unlock(&m_threadMutex); 99     }100 101     return 0;102 103 }104 105 CTask* CThreadPool::GetTaskback()      //取出执行完的任务106 {107     CTask *task;108 109    // if(pthread_mutex_trylock(&m_taskMutex)==0)110 111     if(!taskback->empty())112     {113       task=taskback->front();114       taskback->pop();115       //pthread_mutex_unlock(&m_taskMutex);116 117       return task;118 119     }120 121     return NULL;122 }123 124 int CThreadPool::Create()      //创建线程池125 {126     pthread_t tid=0;127     for(int i=0;i<m_threadNum;i++)128     {129         if(pthread_create(&tid,NULL,ThreadFunc,NULL)!=0)130         {131              cout<<"pthead_create error";132              return -1;133         }134     }135     return 0;136 }137 138 int CThreadPool::clearQueue(queue<CTask*> *a)   139 {140     while(!a->empty())141     {142        a->pop();143     }144 145     delete a;146     return 0;147 }148 149 int CThreadPool::Check()     //防止有任务为执行150 {151    if(!taskQueue1->empty()||!taskQueue2->empty())152        pthread_cond_signal(&m_threadCond);153 }154 155 CThreadPool::~CThreadPool()156 {157     clearQueue(taskQueue1);158     clearQueue(taskQueue2);159     pthread_cond_destroy(&m_threadCond);160 }161 测试文件:    19 #include"CThread.cpp" 20 #include<iostream> 21 #include<sys/time.h> 22  23 using namespace std; 24  25 class CWorkTask:public CTask 26 { 27     public: 28     CWorkTask(){} 29     int Run() 30     { 31         cout<<(char*)this->m_ptrData<<endl; 32         sleep(1); 33         return 0; 34     } 35 }; 36  37 int main() 38 { 39     struct timeval begin,end; 40  41     CWorkTask tt; 42     char str[]="!!!!!!!!!!this is a test"; 43  44     tt.SetData((void*)str); 45     CThreadPool threadpool(5); 46  47     for(int i=0;i<10;i++) 48     { 49         threadpool.AddTask(&tt); 50  51     } 52  53      while(1)      //不让进程退出 54      { 55          sleep(10); 56          threadpool.Check(); 57      } 58  59 }执行结果:


原创粉丝点击